Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/143.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 所以_LINGER选项不会导致close()等待_C++_Sockets_Network Programming - Fatal编程技术网

C++ 所以_LINGER选项不会导致close()等待

C++ 所以_LINGER选项不会导致close()等待,c++,sockets,network-programming,C++,Sockets,Network Programming,我编写以下代码是为了创建一个echo服务器(我写入stdout的数据从我的PC移动到服务器,再返回PC)。在代码中,我在套接字中设置了SO_LINGER选项。因此,当我按下Ctrl+C键导致client.cpp向server.cpp发送FIN时,client.cpp的close()应该等待10秒,以便server.cpp的套接字发回FIN 但我发现,client.cpp在按下Ctrl+C后立即完成执行并退出,,即使是close()函数也没有返回-1,如果另一方在l_linger中提到的时间到期之

我编写以下代码是为了创建一个echo服务器(我写入stdout的数据从我的PC移动到服务器,再返回PC)。在代码中,我在套接字中设置了SO_LINGER选项。因此,当我按下Ctrl+C键导致client.cpp向server.cpp发送FIN时,client.cpp的close()应该等待10秒,以便server.cpp的套接字发回FIN

但我发现,client.cpp在按下Ctrl+C后立即完成执行并退出,,即使是close()函数也没有返回-1,如果另一方在l_linger中提到的时间到期之前没有发送FIN,那么它应该返回-1
我确信服务器没有发送FIN,或者它必须已列在tcpdump中)服务器端没有发送FIN,除非我在其终端上按Ctrl+C。在服务器终端上按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***
}
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;
    }
}
intmain()
{
int clifd;
clifd=套接字(AF\u INET、SOCK\u STREAM、IPPROTO\u TCP);
服务中的sockaddr_;
bzero(&serv,sizeof(serv));
服务sinu family=AF\u INET;
服务单端口=htons(3345);
inet_aton(“127.0.0.1”和(服务地址));
林玲儿;
无符号整数y=sizeof(lin);
lin.l_onoff=1;
林林格=10;
setsockopt(clifd,SOL_-SOCKET,SO_-LINGER,(void*)(&lin),y);
连接(clifd,(sockaddr*)(&serv),sizeof(serv));
int n,m;
字符数据[100];
char-recvd[100];
对于(;;)
{
fgets(数据,100,标准数据);
n=strlen(数据);
库特
为什么客户端的close()没有等待

您没有在客户端中调用
close()
。在调用
close()
之前的
for
循环永远不会退出,因此
close()
永远不会发生

在控制台中键入CTRL-C将导致程序立即退出,而不执行任何剩余操作

由于从未调用过
close()
,因此您的其余问题(是否应该
close()
等待?是否应该使用
closesocket()
?等)没有意义

如果您确实希望能够退出(;)
循环的
,请尝试以下操作:

for(;;)
{
  if(fgets(data, 100,stdin ) == NULL)
    break;
  ... rest of loop goes here ...
然后,在运行客户端程序时,不要使用CTRL-C终止它,而是键入CTRL-D作为行中的唯一字符

为什么客户端的close()没有等待

您没有在客户端中调用
close()
。在调用
close()
之前的
for
循环永远不会退出,因此
close()
永远不会发生

在控制台中键入CTRL-C将导致程序立即退出,而不执行任何剩余操作

由于从未调用过
close()
,因此您的其余问题(是否应该
close()
等待?是否应该使用
closesocket()
?等)没有意义

如果您确实希望能够退出(;)
循环的
,请尝试以下操作:

for(;;)
{
  if(fgets(data, 100,stdin ) == NULL)
    break;
  ... rest of loop goes here ...
然后,当您运行客户端程序时,不要用CTRL-C终止它,而是键入CTRL-D作为行中的唯一字符。

来自MSDN上的参考(如果您不信任MSDN,您可以找到相同的信息)

linger结构维护有关特定套接字的信息,该信息指定当数据排队等待发送并且在套接字上调用closesocket函数时,该套接字应如何工作

因此,它将等待所有数据发送完毕,而不是收到FIN。

来自MSDN上的参考(如果您不信任MSDN,您可以找到相同的信息)

linger结构维护有关特定套接字的信息,该信息指定当数据排队等待发送并且在套接字上调用closesocket函数时,该套接字应如何工作


因此,它将等待所有数据发送完毕,而不是FIN接收完毕。

要展开上面的回答,如果要调用
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)
   {
      ...
   }
   ...
}
#包括
volatile bool stop_now=false;
//当SIGINT(Ctrl+C)时将调用此函数
//已接收,并将设置此全局标志
//将在下面终止您的循环。
无效应用程序_已停止(内部信号)
{
立即停止=真;
}
int main()
{
//设置为捕获Ctrl+C
信号(信号,应用程序停止);
...
//对于(;;)
//变成:
而(!立即停止)
{
...
}
...
}

现在,当您发送SIGINT(通过
Ctrl+C
或通过
kill-s INT
)时,您的程序将正常停止,并调用
close()
函数。您可以从那里开始故障排除。

若要获得
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)
   {
      ...
   }
   ...
}
#包括
volatile bool stop_now=false;
//当SIGINT(Ctrl+C)时将调用此函数
//已接收,并将设置此全局标志
//将在下面终止您的循环。
无效应用程序_已停止(内部信号)
{
立即停止=真;
}
int main()
{
//设置为捕获Ctrl+C
信号(信号,应用程序停止);
...
//对于(;;)
//变成:
而(!立即停止)
{
...
}
...
}
现在,当您发送SIGINT(通过
Ctrl+C
或通过
kill-s INT
)时,您的程序将正常停止,并调用
close()
函数。您可以从那里开始故障排除

因此,client.cpp的close()应该等待10秒,以便server.cpp的套接字发回FIN

这是不正确的。它应该等待所有传出的数据和传出的FIN被发送,或者等待计时器过期。没有任何语句使您有权期望它等待传入的FIN

因此,client.cpp的close()应该等待10秒