我编写了以下代码,以便创建一个 echo服务器(我写入stdout的数据从我的PC移动到服务器并返回到我的PC)。在代码中,我在套接字中设置了SO_LINGER选项。所以,当我按 Ctrl + C 导致client.cpp向server.cpp发送FIN时, client.cpp的close()应该等待server.cpp的套接字发送回FIN 的10秒。
但我发现 client.cpp在 Ctrl + C 被按下后立即完成执行并退出甚至 close()函数没有返回-1 ,如果对方在l_linger中提到的时间到期之前没有发送FIN,它应该拥有它(我确定服务器没有发送FIN或者它必须已在tcpdump中列出。)除非我在其终端上按 Ctrl + C ,否则服务器端不发送FIN。直到我在服务器终端上按 Ctrl + C 的tcpdump显示在屏幕截图中:
上面突出显示的行是客户的FIN。
client.cpp:
int main()
{
int clifd;
clifd=socket(AF_INET,SOCK_STREAM, IPPROTO_TCP);
sockaddr_in serv;
bzero(&serv, sizeof(serv));
serv.sin_family=AF_INET;
serv.sin_port=htons(3345);
inet_aton("127.0.0.1", &(serv.sin_addr));
linger lin;
unsigned int y=sizeof(lin);
lin.l_onoff=1;
lin.l_linger=10;
setsockopt(clifd,SOL_SOCKET, SO_LINGER,(void*)(&lin), y);
connect(clifd, (sockaddr*)(&serv), sizeof(serv));
int n,m;
char data[100];
char recvd[100];
for(;;)
{
fgets(data, 100,stdin );
n=strlen(data);
cout<<"You have written "<<n<<endl;
if(n>0)
{
while(n>0)
{
m=write(clifd,data,n);
n=n-m;
}
}
n=read(clifd, recvd, 100);
cout<<"Server echoed back "<<n<<endl;
if(n>0)
{
while(n>0)
{
m=fputs(data,stdout);
cout<<"m is"<<m<<endl;
fflush(stdout);
n=n-m;
}
//cout<<data<<endl;
}
}
int z=close(clifd);
if(z==-1)
cout<<"close returned -1 "<<endl; ***//this doesn't get printed***
}
server.cpp:
void reflect(int x)
{
int n;
int m;
char data[100];
cout<<"Entered reflect function"<<endl;
for(;;)
{
n=read(x,data, 100);
cout<<"Client sent "<<n<<endl;
if(n>0)
{
while(n>0)
{
m=write(x,data,n);
n=n-m;
}
cout<<"Successfully echoed back to client"<<endl;
}
}//end of for loop
}
int main()
{
sockaddr_in serv;
bzero(&serv, sizeof(serv));
serv.sin_family=AF_INET;
serv.sin_port=htons(3345);
inet_aton("127.0.0.1", &(serv.sin_addr));
int servfd=socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
int x;
x=bind(servfd, (sockaddr*)(&serv), sizeof(serv));
cout<<"Bind returned"<<x<<endl; //this displays x as 0
listen(servfd, 5);
sockaddr cli;
int connfd;
pid_t id=-1;
socklen_t siz=sizeof(cli);
for(;;)
{
if((connfd=accept(servfd, &cli, &siz))>=0)
id=fork();
if(id==0)
reflect(connfd);
else
continue;
}
}
为什么客户关闭()不等待?
答案 0 :(得分:5)
为什么客户关闭()不等待?
您没有在客户端中调用close()
。紧接for
来电之前的close()
循环永不退出,因此close()
永远不会发生。
在控制台中键入 CTRL - C 会导致程序立即退出,而不执行任何剩余的操作。
由于永远不会调用close()
,因此问题的其余部分(应该close()
等待吗?我应该使用closesocket()
等等)是没有意义的。
如果您希望能够退出for(;;)
循环,请尝试以下操作:
for(;;)
{
if(fgets(data, 100,stdin ) == NULL)
break;
... rest of loop goes here ...
然后,当您运行客户端程序时,不要使用 CTRL - C 终止它,而是键入 CTRL - D 是该行的唯一字符。
答案 1 :(得分:3)
要扩展上面的答案,如果您想要调用close()
函数,请对客户进行相对简单的更改:
#include <signal.h>
volatile bool stop_now = false;
// This function will be called when SIGINT (Ctrl+C)
// is received, and will set this global flag that
// will terminate your loop below.
void app_stopped(int sig)
{
stop_now = true;
}
int main()
{
// setup to catch Ctrl+C
signal(SIGINT, app_stopped);
...
// for(;;)
// becomes:
while(!stop_now)
{
...
}
...
}
现在,当您发送SIGINT(通过Ctrl+C
或kill -s INT
)时,您的程序将会正常停止,并且您的close()
函数将被调用。您可以从那里开始进行故障排除。
答案 2 :(得分:2)
来自MSDN上的linger
参考(如果您不信任msdn,您可以找到相同的信息here)
linger结构维护有关特定套接字的信息,该套接字指定当数据排队等待发送并且套接字上调用closesocket函数时该套接字的行为方式。
所以它会等到所有数据都被发送,直到收到FIN为止。
答案 3 :(得分:1)
因此,client.cpp的close()应该等待10秒,以便server.cpp的套接字发回FIN。
这不正确。它应该等待所有传出数据和传出FIN发送,或者等待计时器到期。任何地方都没有任何声明可以让您期望它等待传入的FIN。