1

我目前正在努力让公开可用的 inputpipe 程序与自定义网络的数据包转发器一起工作。

该转发器在启动时获取一个配置文件,并通过网络转发指定的端口。

我现在的问题如下:

当我运行 inputpipe 客户端(连接 USB 设备的 PC)和服务器(模拟 USB 设备的 PC)时,我可以指定服务器将监听的端口。(服务器然后在该特定端口上 bind() 和 listen() )。

我现在的问题是客户端将创建套接字(),然后通过 IP 地址和远程端口连接()到服务器。在此过程中,客户端的操作系统会为它连接的套接字分配一个随机端口号。

由于我需要在实际运行服务器之前指定转发器的传出端口,因此这是不可能的。我在 connect() 之前尝试了 bind() 连接套接字,但这似乎只在目标机器和源机器相同时(通过本地主机连接时)有效,并且在使用实际单独的机器时不起作用。

长话短说:有没有办法为套接字指定远程端口和本地端口?

编辑:我的代码无论出于何种原因都不起作用:

  struct sockaddr_in in_addr;

  /* Struct for the bind call
  */

  struct sockaddr_in out_addr;

  /*
  */ 


  struct hostent* host;
  int fd;
  int opt = 1;

  /* Allocate the new server object */
  self = malloc(sizeof(struct server));
  assert(self != NULL);
  memset(self, 0, sizeof(struct server));

  /* Parse the host:port string */
  self->host = strdup(host_and_port);
  self->port = IPIPE_DEFAULT_PORT;
  p = strchr(self->host, ':');
  if (p) {
    *p = '\0';
    self->port = atoi(p+1);
  }

  /* New socket */
  fd = socket(PF_INET, SOCK_STREAM, 0);
  if (fd < 0) {
    perror("socket");
    server_delete(self);
    return NULL;
  }
 /* Bind the socket to remote port +1 */
  memset(&out_addr, 0, sizeof(out_addr));
  out_addr.sin_family = AF_INET;
  out_addr.sin_port = htons(self->port+1);
  inet_pton(AF_INET, "127.0.0.1", &(out_addr.sin_addr));

  if (bind(fd, (struct sockaddr *)&out_addr, sizeof out_addr)) {
    perror("Binding failed");
    close(fd);
    server_delete(self);
    return NULL;
  } 

  /* Connect the socket to our parsed address */
  host = gethostbyname(self->host);
  if (!host) {
    fprintf(stderr, "Unknown host '%s'\n", self->host);
    close(fd);
    server_delete(self);
    return NULL;
  }
  memset(&in_addr, 0, sizeof(in_addr));
  in_addr.sin_family = AF_INET;
  memcpy(&in_addr.sin_addr.s_addr, host->h_addr_list[0], sizeof(in_addr.sin_addr.s_addr));
  in_addr.sin_port = htons(self->port);

  if (connect(fd, (struct sockaddr*) &in_addr, sizeof(in_addr))) {
    perror("Connecting to inputpipe-server");
    close(fd);
    server_delete(self);
    return NULL;
  }
4

2 回答 2

1

尝试以下方法,这可能会有所帮助

fd = socket(AF_INET, SOCK_STREAM, 0);

// Local
memset(&sa_loc, 0, sizeof(struct sockaddr_in));
sa_loc.sin_family = AF_INET;
sa_loc.sin_port = htons(LOCAL_RANDOM_PORT); /// PUT the port here which you want to open
sa_loc.sin_addr.s_addr = inet_addr(LOCAL_IP_ADDRESS);

ret = bind(fd, (struct sockaddr *)&sa_loc, sizeof(struct sockaddr));
assert(ret != -1);

// Remote
memset(&sa_dst, 0, sizeof(struct sockaddr_in));
sa_dst.sin_family = AF_INET;
sa_dst.sin_port = htons(80);
sa_dst.sin_addr.s_addr = inet_addr("64.233.163.104"); // google :)

ret = connect(fd, (struct sockaddr *)&sa_dst, sizeof(struct sockaddr));
assert(ret != -1);
于 2013-05-30T05:52:10.397 回答
0

我仍然不明白你需要修复源端口的理由,但无论如何......

你很困惑bind(2)listen(2)。它listen(2)是与 互斥的系统调用connect(2)bind(2)只是修复“本地名称”,即套接字的源端口号。

编辑0:

啊,代码...

您正在绑定127.0.0.1- 您无法从这里连接到任何非本地的东西,因此会出现错误。请改用INADDR_ANY您的真实可路由地址。

于 2013-05-30T18:00:41.817 回答