侦听两个不同端口的TCP服务器

时间:2015-09-23 14:00:08

标签: c sockets tcp

我有一个正在侦听两个不同端口的TCP服务器。我在端口8888上创建了两个不同的套接字,在端口6634上创建了一个套接字。我在那些端口上监听,然后在FD_SET中添加两个套接字并将它们传递给select()函数... 当套接字准备好读取时,我检查FD_ISSET以查看我有消息要读取的端口。

当我连接到端口8888时,概念是成功的,我可以发送到服务器并接收...当我ctrl + c客户端时,select函数再次返回1,现在我的accept()失败了.. 。 当我在端口6634上执行相同的操作时,一切正常......代码在select()处停止并等待套接字准备好读取!

谁能告诉我为什么会发生这种情况?

查看附件中的代码

    int main()
    {
        SOCKET          conn_request_skt;   /* socket where connections are accepted */
        char            buf[RBUFLEN], buf1[RBUFLEN];        /* reception buffer */
        uint16_t        lport_n, lport_h, lport_n1, lport_h1;   /* port where the server listens (net/host byte ord resp.) */
        int         bklog = 2;      /* listen backlog */
        SOCKET          s,s1;           
        int         result, n;
        socklen_t addrlen;
        struct sockaddr_in  saddr, caddr;       /* server and client address structures */ 
        int optval,childpid,i; /* flag value for setsockopt */
        int connectcnt; /* number of connection requests */
        fd_set readfds;

        /* Initialize socket API if needed */
        SockStartup();

        /* input server port number */
        lport_h=6634;
        lport_n = htons(lport_h);
        lport_h1=8888;
        lport_n1 = htons(lport_h1);

        /* create the socket */
        printf("Creating first socket\n");
        s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
        if (s == INVALID_SOCKET)
            err_fatal("socket() failed");
        printf("done, socket number %u\n",s);

        /* bind the socket to any local IP address */
        saddr.sin_family      = AF_INET;
        saddr.sin_port        = lport_n;
        saddr.sin_addr.s_addr = INADDR_ANY;
        showAddr("Binding to address first socket", &saddr);
        result = bind(s, (struct sockaddr *) &saddr, sizeof(saddr));
        if (result == -1)
            err_fatal("bind() failed");
        printf("done.\n");

        printf("Creating second socket\n");
        s1 = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
        if (s1 == INVALID_SOCKET)
            err_fatal("socket() failed");
        printf("done, socket number %u\n",s1);

        /* bind the socket to any local IP address */

        saddr.sin_port=lport_n1;

        showAddr("Binding to address second socket", &saddr);
        result = bind(s1, (struct sockaddr *) &saddr, sizeof(saddr));
        if (result == -1)
            err_fatal("bind() failed");
        printf("done.\n");


        /* listen */
        printf ("Listening at socket %d with backlog = %d \n",s,bklog);
        result = listen(s, bklog);
        if (result == -1)
            err_fatal("listen() failed");
        printf("done.\n");

        printf ("Listening at socket %d with backlog = %d \n",s1,bklog);
        result = listen(s1, bklog);
        if (result == -1)
            err_fatal("listen() failed");
        printf("done.\n");
for (;;)
    {


        FD_ZERO(&readfds);          /* initialize the fd set */
        FD_SET(s, &readfds);
        FD_SET(s1, &readfds); /* add socket fd */
        printf("here \n");

        printf("result bifore select is %d \n", result);
        result=select(s1+1, &readfds, 0, 0, 0);

        printf("result after select is %d \n", result);

        if(result<0)
            {
                err_fatal("select() failed");

            }
        if(result>0)
        {

            if(FD_ISSET(s,&readfds))
            {

                conn_request_skt=s;
                /* accept next connection */
                addrlen = sizeof(struct sockaddr_in);
                s = accept(conn_request_skt, (struct sockaddr *) &caddr, &addrlen);
                if (s == INVALID_SOCKET)
                err_fatal("accept() failed");
                showAddr("Accepted connection from", &caddr);
                printf("new socket: %u\n",s);
                /* serve the client on socket s */
                for (;;)
                {
                    n=recv(s, buf, RBUFLEN-1, 0);
                    if (n < 0)
                    {
                        printf("Read error\n");
                        closesocket(s);
                        printf("Socket %d closed\n", s);
                        break;
                    }
                    else if (n==0)
                    {
                        printf("Connection closed by party on socket %d\n",s);
                        //closesocket(s);
                        break;
                    }
                    else
                    {
                        printf("Received line from socket %03d :\n", s);
                        buf[n]=0;
                        printf("[%s]\n",buf);
                        if(writen(s, buf, n) != n)
                        printf("Write error while replying\n");
                        else
                        printf("Reply sent\n");
                    }   
                }
            }


            if(FD_ISSET(s1,&readfds))
            {
                conn_request_skt=s1;
                /* accept next connection */
                addrlen = sizeof(struct sockaddr_in);
                printf("bifore accept! \n");
                s1 = accept(conn_request_skt, (struct sockaddr *) &caddr, &addrlen);
                if (s1 == INVALID_SOCKET)
                err_fatal("accept() failed");
                showAddr("Accepted connection from", &caddr);
                printf("new socket: %u\n",s1);
                /* serve the client on socket s */
                for (;;)
                {
                    n=recv(s1, buf, RBUFLEN-1, 0);
                    if (n < 0)
                    {
                        printf("Read error\n");
                        closesocket(s1);
                        printf("Socket %d closed\n", s1);
                        break;
                    }
                    else if (n==0)
                    {
                        printf("Connection closed by party on socket %d\n",s1);
                        //closesocket(s);
                        break;
                    }
                    else
                    {
                        printf("Received line from socket %03d :\n", s1);
                        buf[n]=0;
                        printf("[%s]\n",buf);
                        if(writen(s1, buf, n) != n)
                        printf("Write error while replying\n");
                        else
                        printf("Reply sent\n");
                    }   
                }
            }
        }
    }
}

2 个答案:

答案 0 :(得分:2)

使用以下命令创建第一个侦听器套接字:

s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

然后接受数据套接字:

 conn_request_skt=s;
 s = accept(conn_request_skt, (struct sockaddr *) &caddr, &addrlen);

请参阅?下一个循环,当您要选择侦听器套接字时,s不再保留该套接字,而是(已关闭)数据套接字。

解决方案是为侦听器套接字和数据套接字使用不同的变量(conn_request_skt只是混淆了问题)。

答案 1 :(得分:1)

您正在使用accept()调用的结果覆盖套接字变量s1。所以s1现在包含你实际读取的套接字的描述符。然后关闭该套接字。但是在主循环的下一个传递中,您检查该(现在已关闭)描述符的可读性,该描述符不起作用。

我认为在这种情况下最好不要重复使用变量。对实际连接套接字使用新变量,以便在s1中保留原始侦听套接字。