【问题标题】:How to create multiple tcp connections between server and client如何在服务器和客户端之间创建多个 tcp 连接
【发布时间】:2012-10-16 22:22:33
【问题描述】:

我是 Unix/Linux 网络编程的新手,所以我在下面编写了服务器-客户端程序。在这段代码中,客户端和服务器之间有一个套接字,客户端请求服务器,然后服务器响应 1 到 100 个数字到客户。所以我的问题是我们如何在不使用线程的情况下使用 3 个套接字(tcp 连接)来完成这个过程? (例如,第一个套接字运行,然后第二个运行,然后第三个运行,然后再次运行。)你有什么建议吗?

客户端.c

int main()
{

int sock;
struct sockaddr_in sa;
int ret;
char buf[1024];
int x;

sock = socket (AF_INET, SOCK_STREAM, 0);

bzero (&sa, sizeof(sa));
sa.sin_family = AF_INET;
sa.sin_port = htons(SERVER_PORT);
inet_pton (AF_INET, SERVER_IP, &sa.sin_addr);

ret = connect (sock,
(const struct sockaddr *) &sa,sizeof (sa));

if (ret != 0) {
    printf ("connect failed\n");
    exit (0);
}

x = 0;
while (x != -1) {
    read (sock, buf , sizeof(int));
    x = ntohl(*((int *)buf));
    if (x != -1)
    printf ("int rcvd = %d\n", x);
}

close (sock);

exit (0);

}

服务器.c

int main()
{

int list_sock;
int conn_sock;
struct sockaddr_in sa, ca;
socklen_t ca_len;
char buf[1024];
int i;
char ipaddrstr[IPSTRLEN];

list_sock = socket (AF_INET, SOCK_STREAM, 0);

bzero (&sa, sizeof(sa));
sa.sin_family = AF_INET;
sa.sin_addr.s_addr = htonl(INADDR_ANY);
sa.sin_port = htons(SERVER_PORT);
bind (list_sock,(struct sockaddr *) &sa,sizeof(sa));

listen (list_sock, 5);

while (1){

    bzero (&ca, sizeof(ca));
    ca_len = sizeof(ca); // important to initialize
    conn_sock = accept (list_sock,(struct sockaddr *) &ca,&ca_len);

    printf ("connection from: ip=%s port=%d \n",inet_ntop(AF_INET, &(ca.sin_addr),
        ipaddrstr, IPSTRLEN),ntohs(ca.sin_port));

    for (i=0; i<100; ++i){

        *((int *)buf) = htonl(i+20);
        // we using converting to network byte order

        write (conn_sock, buf, sizeof(int));

    }

    * ((int *)buf) = htonl(-1);
    write (conn_sock, buf, sizeof(int));

    close (conn_sock);

    printf ("server closed connection to client\n");

}
}

【问题讨论】:

  • 你的意思是你想让服务器在三个不同的套接字上旋转?然后他们需要不同的端口。这是你想要的吗?
  • 是的,它们会在三个不同的插槽上旋转,但我认为一个端口就足够了?
  • 据我所知服务器套接字不能绑定到同一个端口。然后他们应该如何确定哪个应该“接受”连接?我当时看到的唯一可能性是关闭套接字并打开一个新的。但是这样做有什么好处呢?

标签: c linux sockets ubuntu


【解决方案1】:

我认为最好查看优秀资源Beej's Guide to Netwokr Programming,其中详细介绍了这一点。他还提供了一些很好的示例,您可以将其用作起点,并且涵盖了包括 Windows 在内的所有主要平台。

基本上你会这样做:

socket()
bind()
listen()
accept()

accept() 返回连接到唯一客户端的套接字。然后,您将使用 select、poll 或 epoll 来确定这些套接字上的数据何时可用。我建议您可以查看这些 API 的手册页和 Beej 的指南。这是我第一次学习网络编程的地方。

查看您的代码,您的内部循环是错误的。当您接受连接时,您需要将其添加到列表或其他内容中。目前,您覆盖它并松开它。您应该使用 (e)poll 或 select 告诉您哪个有数据。您可以随时写信给他们中的任何一个。再次查看 Beej 指南中的示例,它们很有帮助。

【讨论】:

    【解决方案2】:

    可能不是你想要的,但是我觉得你可以试试epoll,有一个简单的例子

    typedef struct event_loop
    {
        int max_event;
        int epfd;
    }event_loop;
    
    event_loop* create_event_loop()
    {
        event_loop *ep = malloc(sizeof(event_loop));
        ep->max_event = 512;
        ep->epfd = epoll_create(512);
        return ep; 
    }
    int add_event(event_loop *ep, int fd) 
    {
        epoll_event ee; 
        ee.data.fd = fd; 
        ee.event = EPOLLIN | EPOLLPRI;
        epoll_ctl(ep->epfd, EPOLL_CTL_ADD, fd, &ee);
    }
    void event_main(event_loop *ep, int listenfd)
    {
        epoll_event events[512];
        int nfds, i, newfd;
        while(1)
        {   
            if(nfds = epoll_wait(ep->epfd, events, 512, -1) == -1) 
                exit(1);
            for(i = 0; i < nfds; i++)
            {   
                if(events[nfds].data.fd == listenfd)
                {   
                    newfd = accept(listenfd, NULL, NULL);
                    add_event(ep, newfd);
                }
                else
                {
                    //do what you want
                }
            }
        }
    }
    

    epoll 是一种高效的解决方案,只需man epoll 获取更多信息

    【讨论】:

      猜你喜欢
      • 2016-04-10
      • 2015-01-19
      • 1970-01-01
      • 2021-11-06
      • 2022-01-17
      • 2013-05-07
      • 2011-05-20
      • 2021-08-12
      • 2012-04-24
      相关资源
      最近更新 更多