从每个节点到每个其他节点建立TCP连接的问题

时间:2015-11-03 22:36:57

标签: c++ sockets tcp

我有一些n个节点,我想通过TCP将它们相互连接。我正在实现以下伪代码:

Node ids in {1, 2, ..., n}
For node having node id k :
  act as the client and try to connect to nodes with id > k
  act as the server and listen for connection requests from nodes with id < k
    while tracking which of the nodes connected in each step

伪代码中的两个步骤都实现为for循环。 值得注意的是,所有tcp连接都使用相同的端口。该代码适用于2个节点,但对于3个节点,第二个侦听功能位于具有id 3的节点(正在侦听连接)打印错误&#34;地址已在使用&#34; 。我相信对accept()函数的调用会返回错误。

我在C++linux(Ubuntu 15.04)编程(使用套接字)。

我在网上搜索并得出结论,两个以上的客户端可以连接到同一个端口(因为服务器上的套接字不同)。我做错了什么?

编辑: 实际代码(只是相关功能的一小部分)。假设ip_addrs,node_rank,num_nodes被适当地初始化。

// port for the tcp connection
int port = 25551;
// ip address of the local node
string ip_addr;
// sockets for talking to the nodes
vector <int> sockets;

static int exchange_node_rank(int sock) {
    char msg[10];
    sprintf(msg, "%d", node_rank);
    write(sock, msg, sizeof(msg));
    read(sock, msg, sizeof(msg));
    int rank;
    sscanf(msg, "%d", &rank);
    return rank;
}

// servername is only for client, it *is* NULL for server
static pair<int, int> sock_connect(const char *servername) {
    struct addrinfo *resolved_addr = NULL;
    struct addrinfo *iterator;
    char service[6];
    int sockfd = -1;
    int listenfd = 0;
    int tmp;
    struct addrinfo hints = {.ai_flags = AI_PASSIVE,
                             .ai_family = AF_INET,
                             .ai_socktype = SOCK_STREAM};
    if(sprintf(service, "%d", port) < 0) goto sock_connect_exit;
    /* Resolve DNS address, use sockfd as temp storage */
    sockfd = getaddrinfo(servername, service, &hints, &resolved_addr);
    if(sockfd < 0) {
        fprintf(stderr, "%s for %s:%d\n", gai_strerror(sockfd), servername,
                port);
        goto sock_connect_exit;
    }
    /* Search through results and find the one we want */
    for(iterator = resolved_addr; iterator; iterator = iterator->ai_next) {
        sockfd = socket(iterator->ai_family, iterator->ai_socktype,
                        iterator->ai_protocol);
        if(sockfd >= 0) {
            if(servername) {
                /* Client mode.  Initiate connection to remote */
                while((tmp = connect(sockfd, iterator->ai_addr,
                                     iterator->ai_addrlen))) {
                }
            } else {
                /* Server mode.
           Set up listening socket an accept a connection */
                listenfd = sockfd;
                sockfd = -1;
                if(bind(listenfd, iterator->ai_addr, iterator->ai_addrlen))
                    goto sock_connect_exit;
                listen(listenfd, 1);
                sockfd = accept(listenfd, NULL, 0);
            }
        }
    }
sock_connect_exit:
    if(listenfd) close(listenfd);
    if(resolved_addr) freeaddrinfo(resolved_addr);
    if(sockfd < 0) {
        if(servername)
      fprintf(stderr, "Couldn't connect to %s:%d\n", servername, port);
        else {
            perror("server accept");
            fprintf(stderr, "accept() failed\n");
        }
    }
    int rank = exchange_node_rank(sockfd);
    return pair<int, int>(sockfd, rank);
}

void establish_tcp_connections (const vector <string> & ip_addrs) {
  // try to connect to nodes greater than node_rank
  for(int i = num_nodes - 1; i > node_rank; --i) {
    cout << "trying to connect to node rank " << i << endl;
    pair <int, int> p = sock_connect(ip_addrs[i].c_str());
    cout << "connected to node rank " << i << endl << endl;
    assert(p.second == i);
    // set the socket
    sockets[i] = p.first;
  }

  // listen to nodes trying to connect (having id less than node_rank).
  // make sure that the caller is correctly identified with its id!
  for(int i = node_rank - 1; i >= 0; --i) {
    cout << "listening for nodes with lesser rank" << endl;
    pair <int, int> p = sock_connect((char *)NULL);
    cout << "connected to node rank " << p.second << endl << endl;
    assert(p.second < node_rank);
    // set the socket
    sockets[p.second] = p.first;
  }
}

0 个答案:

没有答案