我有一个正在侦听两个不同端口的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");
}
}
}
}
}
}
答案 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中保留原始侦听套接字。