同时使用相同的套接字强制实施本地和远程端口

时间:2013-05-29 19:12:37

标签: c sockets networking port

我目前正致力于将公开的输入管道程序与Packet Forwarder一起用于自定义网络。

此转发器在启动期间获取配置文件,并通过网络转发指定的端口。

我现在的问题如下:

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

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

由于我需要在实际运行服务器之前指定转发器的传出端口,这使得它无法实现。我在connect()之前尝试了bind()套接字,但这只在目标和源机器相同时(通过localhost连接时)才有效,并且在使用实际的单独机器时不起作用。

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

编辑:我的代码无论出于何种原因都无效:

  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;
  }

2 个答案:

答案 0 :(得分: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);

答案 1 :(得分:1)

我仍然不理解您需要修复源端口的原因,但无论如何......

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

编辑0:

啊,代码......

您绑定到127.0.0.1 - 您无法从此处连接到任何非本地连接,因此错误。请改用INADDR_ANY或您真实的可路由地址。