服务器在不同的IP上

时间:2013-11-19 20:32:38

标签: c linux sockets networking network-programming

我正在尝试创建应该在具有多个NIC(eth0,eth1)的计算机上运行的TCP Server。每个NIC都有自己的网络IP,我基本上希望能够同时连接到每个IP上运行的服务器。但是目前我只能将(netcat)连接到第一个接口IP eth0,当我尝试使用eth1时,即使我的服务器只运行在eth1上,我也会收到“拒绝连接”。

我不确定我的服务器代码是否有问题(如下)。我使用setsockopt()绑定到所需的接口,并使用接口IP(通过ioctl检索),netstat显示服务器正在侦听正确的ip:端口,但是我无法连接到eth1上的接口。

#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <net/if.h>
#include <sys/ioctl.h>
#include <stdlib.h>
#include <string.h>

#define MAX_SIZE 255

struct in_addr getIfIp(char* ifName)
{
  int sockfd;
  struct ifreq ifr;

  sockfd = socket(AF_INET, SOCK_STREAM, 0);
  ifr.ifr_addr.sa_family = AF_INET;
  strncpy(ifr.ifr_name, ifName, IFNAMSIZ-1);
  if (ioctl(sockfd, SIOCGIFADDR, &ifr) < 0) {
    fprintf(stderr, "ioctl failed\n");
  }
  close(sockfd);

  return ((struct sockaddr_in*)&ifr.ifr_addr)->sin_addr;
}

int startServer(char* ifName, unsigned short port)
{
  int sock_descriptor, conn_desc;
  struct sockaddr_in serv_addr, client_addr;
  socklen_t size = sizeof(client_addr);
  char buff[MAX_SIZE];

  if (ifName == NULL || port == 0) {
    fprintf(stderr, "invalid server parameters\n");
    return -1;
  }

  sock_descriptor = socket(AF_INET, SOCK_STREAM, 0);
  if(sock_descriptor < 0) {
    fprintf(stderr, "Failed creating socket\n");
    return sock_descriptor;
  }

  if (setsockopt(sock_descriptor, SOL_SOCKET, SO_BINDTODEVICE, ifName, strlen(ifName)) < 0) {
    fprintf(stderr, "Failed setting socket option\n");
    return -1;
  }

  bzero((char *)&serv_addr, sizeof(serv_addr));
  serv_addr.sin_family = AF_INET; // AddressFamily = Internet address
  serv_addr.sin_addr = getIfIp(ifName);//INADDR_ANY;
  serv_addr.sin_port = htons(port);

  // bind the address to the socket file descriptor
  if (bind(sock_descriptor, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
    fprintf(stderr, "Failed to bind\n");
    return -1;
  } else {
    printf("bound to %s\n", inet_ntoa(serv_addr.sin_addr));
  }

  // Now start listening
  if (listen(sock_descriptor, 0) < 0){
    fprintf(stderr, "Listen failed");
    return -1;
  } else {// max queue of pending connections
    printf("Listening on port %hu ...\n", port);
  }    
  conn_desc = accept(sock_descriptor, (struct sockaddr *)&client_addr, &size);   
  if (conn_desc == -1) {
    fprintf(stderr, "Failed accepting connection\n");
  } else {
    fprintf(stderr, "Connected\n");
  }

  close(conn_desc);
  close(sock_descriptor);
  return 0;
}

对此有任何帮助将不胜感激。

[编辑] 正如我的评论中所提到的,我注意到的一件有趣的事情是,一旦我连接到任何一个接口,我只能再次连接到此接口并连接尝试到另一个失败(对于eth0和eth1),直到重新启动。 另外我想我现在会继续使用INADDR_ANY,但是我真的很想听听是否有人可以解释为什么我不能连接到单独的听众(我的代码在这里)?

1 个答案:

答案 0 :(得分:1)

让套接字侦听任何接口使用INADDR_ANY作为侦听器地址...

serv_addr.sin_addr = INADDR_ANY;

并移除对setsockopt()的调用。


我不确定0的后台日志大小是否合理。此外,代码错过了测试listen()的调用结果。


最后int size应为socklen_t size