侦听两个不同端口的 TCP 服务器
Posted
技术标签:
【中文标题】侦听两个不同端口的 TCP 服务器【英文标题】:TCP server that listen on two different ports 【发布时间】:2015-09-23 14:00:07 【问题描述】:我有一个监听两个不同端口的 TCP 服务器。我创建了两个不同的套接字,一个在端口 8888 上,一个在端口 6634 上。我侦听这些端口,然后在 FD_SET 中添加两个套接字并将它们传递给 select() 函数... 当套接字准备好读取时,我会检查 FD_ISSET 以查看我在哪个端口上有要读取的消息。
当我连接到端口 8888 时,构想成功,我可以向服务器发送并接收......当我 ctrl+c 客户端时,选择函数再次返回 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");
【问题讨论】:
【参考方案1】:第一个侦听器套接字是通过以下方式创建的:
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
只是混淆了问题)。
【讨论】:
【参考方案2】:您正在用 accept() 调用的结果覆盖您的套接字变量 s1。所以 s1 现在包含您实际从中读取的套接字的描述符。然后你关闭那个套接字。但是在主循环的下一个循环中,您检查该(现已关闭)描述符的可读性,这不起作用。
我相信在这种情况下最好不要重用变量。为实际的连接socket使用一个新变量,这样就可以在s1中保留原来的监听socket。
【讨论】:
以上是关于侦听两个不同端口的 TCP 服务器的主要内容,如果未能解决你的问题,请参考以下文章