【问题标题】:Making a proxy for unix using C socket使用 C 套接字为 unix 制作代理
【发布时间】:2018-03-08 15:28:42
【问题描述】:

我正在尝试创建两个代理,将两个不同的虚拟机连接在一起。他们应该像这样连接

vm1(telnet) proxy1 proxy2 vm2(telnet daemon)

用户将打开 vm1 和 vm2,然后打开另一个 vm1 实例。在 vm1 上运行 proxy1,在 vm2 上运行 proxy2,然后在第二个 vm1 上通过 telnet 连接到 proxy1。

一旦用户通过 vm1 连接到 proxy1,proxy1 就应该连接到 proxy2。 Proxy2 将发送 vm2 显示的内容,即登录提示。它会将其发送到proxy1,然后发送到vm1。用户应该能够输入 vm1 并将每一行发送到 proxy1,然后是 proxy2,然后是 vm2,就好像他们一直在 vm2 一样。相反,我从 vm2 的登录页面中得到了几个词,但它主要是随机字符和一些 tv 静态字符。它不断向我发送大量随机字符,直到我关闭所有内容。

这是我的代码(cproxy.c 是 proxy1,sproxy.c 是 proxy2)

cproxy.c

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>

#define MAX_PENDING 5
#define MAX_LINE 1024

struct sockaddr_in LocalTelnetAddress;
struct sockaddr_in SproxyAddress;
struct hostent *hp;
struct timeval tv;

int setUpTelnetConnection(int port){
    bzero((char *)&LocalTelnetAddress, sizeof(LocalTelnetAddress));
    LocalTelnetAddress.sin_family = AF_INET;
    LocalTelnetAddress.sin_addr.s_addr = INADDR_ANY;
    LocalTelnetAddress.sin_port = htons(port); // Change 5200

    // Create socket.
    int localTelnetSocket = socket(PF_INET, SOCK_STREAM, 0);
    if (localTelnetSocket < 0) {
        fprintf(stderr, "ERROR: c telnet socket.\n");
        exit(1);
    }

    // Bind socket.
    if (bind(localTelnetSocket, (struct sockaddr *) &LocalTelnetAddress, sizeof(LocalTelnetAddress)) < 0) {
        fprintf(stderr, "ERROR: c telnet bind.\n");
        exit(1);
    }

    return localTelnetSocket;
}

int setUpSproxyConnection(char *host, int port)
{
    hp = gethostbyname(host);
    bzero((char *)&SproxyAddress, sizeof(SproxyAddress));
    SproxyAddress.sin_family = AF_INET;
    bcopy(hp->h_addr, (char *)&SproxyAddress.sin_addr, hp->h_length);
    SproxyAddress.sin_port = htons(port);  //change 6200


    // Create the socket.
    int sproxySocket = socket(PF_INET, SOCK_STREAM, 0);
    if (sproxySocket < 0) {
        fprintf(stderr, "ERROR: sproxy socket.\n");
        exit(1);
    }

    return sproxySocket;
}

int main(int argc, char * argv[]){

    fd_set readfds;
    int rv;
    int n, len = 0;
    struct timeval tv;

    char buf1[MAX_LINE];
    socklen_t len1;
    char buf2[MAX_LINE];

    int port1;
    int port2;
    int localTelnetSocket;
    int sproxySocket;
    if(argc == 4){
        port1 = atoi(argv[1]);
        port2 = atoi(argv[3]);
        localTelnetSocket = setUpTelnetConnection(port1);
        sproxySocket = setUpSproxyConnection(argv[2],port2);
    }
    else{
        fprintf(stderr, "illegal argc\n");
        exit(1);
    }

    listen(localTelnetSocket, MAX_PENDING);
  //  int len = sizeof(LocalTelnetAddress);
    // Connect local telnet
    int localTelnet_s = accept(localTelnetSocket, (struct sockaddr *)&LocalTelnetAddress, &len1);
    if (localTelnet_s < 0) {
        perror("simplex-talk: accept");
        exit(1);
    }

    // Connect sproxy
    int sproxy_s = connect(sproxySocket, (struct sockaddr *) &SproxyAddress, sizeof(SproxyAddress));
    if (sproxy_s < 0) {
        fprintf(stderr, "ERROR connecting to sproxy.\n");
        exit(EXIT_FAILURE);
    }

    while(1){
        // clear the set ahead of time
        FD_ZERO(&readfds);

        // add our descriptors to the set
        FD_SET(localTelnet_s, &readfds);
        FD_SET(sproxySocket, &readfds);

        // find the largest descriptor, and plus one.

        if (localTelnet_s > sproxySocket) n = localTelnet_s + 1;
        else n = sproxySocket +1;


        // wait until either socket has data ready to be recv()d (timeout 10.5 secs)
        tv.tv_sec = 10;
        tv.tv_usec = 500000;

        rv = select(n, &readfds, NULL, NULL, &tv);


        if (rv == -1) {
            perror("select"); // error occurred in select()
        } else if (rv == 0) {
            printf("Timeout occurred!  No data after 10.5 seconds.\n");
        } else {
            // one or both of the descriptors have data
            if (FD_ISSET(localTelnet_s, &readfds)) {
                memset(buf1,0,strlen(buf1));
                len = recv(localTelnet_s, buf1, sizeof(buf1), 0);
                send(sproxySocket, buf1, sizeof(buf1), 0);
               // printf("%s", buf1);
            }
            if (FD_ISSET(sproxySocket, &readfds)) {
                memset(buf2,0,strlen(buf2));
                len = recv(sproxySocket, buf2, sizeof(buf2), 0);
                send(localTelnet_s, buf2, sizeof(buf2), 0);
            }
        }
    }
    return 0;
}

sproxy.c

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>

#define MAX_PENDING 5
#define MAX_LINE 1024

struct sockaddr_in TelnetDaemonAddress;
struct sockaddr_in CproxyAddress;
struct hostent *hp;
char *ip = "127.0.0.1";
//struct hostent *hp;
struct timeval tv;

int setUpCproxyConnection(int port)
{
    bzero((char *)&CproxyAddress, sizeof(CproxyAddress));
    CproxyAddress.sin_family = AF_INET;
    CproxyAddress.sin_addr.s_addr = INADDR_ANY;
    CproxyAddress.sin_port = htons(port);

    // Create  socket.
    int cproxySocket = socket(PF_INET, SOCK_STREAM, 0);
    if (cproxySocket < 0) {
        fprintf(stderr, "ERROR: cproxy socket.\n");
        exit(EXIT_FAILURE);
    }

    // Bind socket
    if (bind(cproxySocket, (struct sockaddr *) &CproxyAddress, sizeof(CproxyAddress)) < 0) {
        fprintf(stderr, "ERROR: cproxy bind.\n");
        exit(EXIT_FAILURE);
    }

    return cproxySocket;
}

int setUpTelnetDaemonConnection()
{
    hp = gethostbyname("127.0.0.1");
    bzero((char *)&TelnetDaemonAddress, sizeof(TelnetDaemonAddress));
    TelnetDaemonAddress.sin_family = AF_INET;
    bcopy(hp->h_addr, (char *)&TelnetDaemonAddress.sin_addr, hp->h_length);
    TelnetDaemonAddress.sin_port = htons(23);  //change 6200


    // Create the socket.
    int telnetDaemonSocket = socket(PF_INET, SOCK_STREAM, 0);
    if (telnetDaemonSocket < 0) {
        fprintf(stderr, "ERROR: telnetDaemonSocket.\n");
        exit(1);
    }

    return telnetDaemonSocket;
}

int main(int argc, char * argv[]){

    fd_set readfds;
    int rv;
    int n, len = 0;
    struct timeval tv;

    char buf1[MAX_LINE];
    socklen_t len1;
    char buf2[MAX_LINE];


    int port;
    int cproxySocket;
    int telnetDaemonSocket;


    if(argc == 2){
        port = atoi(argv[1]);
        cproxySocket = setUpCproxyConnection(port);
        telnetDaemonSocket = setUpTelnetDaemonConnection();
    }
    else{
        fprintf(stderr, "illegal argc\n");
        exit(1);
    }

    // Connect cproxy
    listen(cproxySocket, MAX_PENDING);
   // int len = sizeof(CproxyAddress);
    int cproxy_s = accept(cproxySocket, (struct sockaddr *) &CproxyAddress, &len1);


    if (cproxy_s < 0) {
        fprintf(stderr, "ERROR: cproxy accept.\n");
        exit(1);
    }

    // Connect telnet daemon
    if (connect(telnetDaemonSocket, (struct sockaddr *) &TelnetDaemonAddress, sizeof(TelnetDaemonAddress)) < 0) {
        fprintf(stderr, "ERROR: telnet daemon connect.\n");
        exit(1);
    }

    while(1){
        // clear the set ahead of time
        FD_ZERO(&readfds);

        // add our descriptors to the set
        FD_SET(cproxy_s, &readfds);
        FD_SET(telnetDaemonSocket, &readfds);


        // find the largest descriptor, and plus one.

        if (cproxy_s > telnetDaemonSocket) n = cproxy_s + 1;
        else n = telnetDaemonSocket +1;

        // wait until either socket has data ready to be recv()d (timeout 10.5 secs)
        tv.tv_sec = 10;
        tv.tv_usec = 500000;
        rv = select(n, &readfds, NULL, NULL, &tv);

        if (rv == -1) {
            perror("select"); // error occurred in select()
        } else if (rv == 0) {
            printf("Timeout occurred!  No data after 10.5 seconds.\n");
        } else {
            // one or both of the descriptors have data
            if (FD_ISSET(cproxy_s, &readfds)) {
                memset(buf1,0,strlen(buf1));
                len = recv(cproxy_s, buf1, sizeof(buf1), 0);
                send(telnetDaemonSocket, buf1, sizeof(buf1), 0);
            }
            if (FD_ISSET(telnetDaemonSocket, &readfds)) {
                memset(buf2,0,strlen(buf2));
                len = recv(telnetDaemonSocket, buf2, sizeof(buf2), 0);
                send(cproxy_s, buf2, sizeof(buf2), 0);
                //printf("%s", buf2);
            }
        }
    }
    return 0;
}

【问题讨论】:

  • 除了完全缺乏您真正想要添加的错误检查之外,您只想发送收到的字节数。
  • 所以除了向所有相关的系统调用添加错误检查之外,删除这些行memset( ...。并将send(.., ..., sizeof ..., 0); 替换为send(.., ..., len, 0);
  • 好吧,你是最棒的。现在可以了。非常感谢您的帮助。

标签: c sockets network-programming telnet


【解决方案1】:
len = recv(localTelnet_s, buf1, sizeof(buf1), 0);
send(sproxySocket, buf1, sizeof(buf1), 0);

你忽略了:

  1. 流结束,由len == 0 发出信号。
  2. 错误,由len == -1 表示。
  3. 接收到的字节数,如果为正则由len 发出信号。

应该更像:

len = recv(localTelnet_s, buf1, sizeof(buf1), 0);
if (len == 0)
    // close both sockets and remove them from the FD sets
else if (len == -1)
{
    perror("recv"); // at least
    // close both sockets and remove them from the FD sets
}
else
{
    send(sproxySocket, buf1, len, 0);
}

【讨论】:

    【解决方案2】:

    除了完全没有您真正想要添加的错误检查之外,您只想发送收到的字节数。

    因此,除了为所有相关系统调用添加错误检查之外,删除这些行 memset( .... 并将 send(.., ..., sizeof ..., 0); 替换为 send(.., ..., len, 0);

    【讨论】:

      猜你喜欢
      • 2016-07-31
      • 1970-01-01
      • 1970-01-01
      • 2012-05-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-07
      • 1970-01-01
      相关资源
      最近更新 更多