send()崩溃了我的程序

时间:2011-05-28 16:47:05

标签: c++

我正在运行服务器和客户端。我正在计算机上测试我的程序。

这是服务器中向客户端发送数据的功能:

int sendToClient(int fd, string msg) {

    cout << "sending to client " << fd << " " << msg <<endl;
    int len = msg.size()+1;
    cout << "10\n";
    /* send msg size */
    if (send(fd,&len,sizeof(int),0)==-1) {
        cout << "error sendToClient\n";
        return -1;
    }
    cout << "11\n";
    /* send msg */
    int nbytes = send(fd,msg.c_str(),len,0); //CRASHES HERE
    cout << "15\n";
    return nbytes;
}

当客户端退出时,它发送到服务器“BYE”,服务器正在使用上述功能回复它。我将客户端连接到服务器(在一台计算机上完成,2个终端),当客户端退出服务器崩溃时 - 它永远不会打印15。 任何想法为什么?任何想法如何测试为什么?

谢谢。

编辑:这就是我关闭客户端的方式:

void closeClient(int notifyServer = 0) {

/** notify server before closing */
if (notifyServer) {
    int len = SERVER_PROTOCOL[bye].size()+1;
    char* buf = new char[len];
    strcpy(buf,SERVER_PROTOCOL[bye].c_str());   //c_str - NEED TO FREE????
    sendToServer(buf,len);
    delete[] buf;
}
close(_sockfd);
}

顺便说一下,如果我跳过这段代码,意思就是离开close(_sockfd)而不通知服务器一切正常 - 服务器不会崩溃。

编辑2:这是strace.out:

的结束
5211  recv(5, "BYE\0", 4, 0)            = 4
5211  write(1, "received from client 5 \n", 24) = 24
5211  write(1, "command: BYE msg: \n", 19) = 19
5211  write(1, "BYEBYE\n", 7)           = 7
5211  write(1, "response = ALALA!!!\n", 20) = 20
5211  write(1, "sending to client 5 ALALA!!!\n", 29) = 29
5211  write(1, "10\n", 3)               = 3
5211  send(5, "\t\0\0\0", 4, 0)         = 4
5211  write(1, "11\n", 3)               = 3
5211  send(5, "ALALA!!!\0", 9, 0)       = -1 EPIPE (Broken pipe)
5211  --- SIGPIPE (Broken pipe) @ 0 (0) ---
5211  +++ killed by SIGPIPE +++

破管可以杀死我的程序?为什么不通过send()??

返回-1

6 个答案:

答案 0 :(得分:11)

您可能希望在标志中指定MSG_NOSIGNAL

int nbytes = send(fd,msg.c_str(), msg.size(), MSG_NOSIGNAL);

答案 1 :(得分:4)

由于Unix中的“功能”在尝试发送远程对等已关闭的套接字时引发了SIGPIPE,因此您获得了SIGPIPE。由于您不处理信号,因此会调用默认的信号处理程序,它会中止/崩溃您的程序。

要获得您想要的行为(即make send()返回错误,而不是发出信号),请将其添加到程序的启动例程(例如main()的顶部):

#include <signal.h>

int main(int argc, char ** argv)
{
   [...]
   signal(SIGPIPE, SIG_IGN); 

答案 2 :(得分:3)

客户端可能在服务器完成发送之前退出,从而打破了它们之间的套接字。从而使发送崩溃。

link

  

此套接字已连接但是   连接现在已经破裂。在这   case,send生成一个SIGPIPE信号   第一;如果该信号被忽略或   阻止,或者如果其处理程序返回,   然后用EPIPE发送失败。

答案 3 :(得分:1)

如果客户端在服务器的第二个send之前退出,并且连接未正确处理,则服务器会一直挂起,这可能会导致崩溃。

只是一个猜测,因为我们不知道服务器和客户端实际上做了什么。

答案 4 :(得分:1)

我发现以下代码行很奇怪,因为您定义了int len = msg.size()+1;

int nbytes = send(fd,msg.c_str(),len,0); //CRASHES HERE

如果定义int len = msg.size();会怎样?

答案 5 :(得分:0)

如果您使用的是Linux,请尝试在strace内运行服务器。这会将大量有用的数据写入日志文件。

strace -f -o strace.out ./server

然后看一下日志文件的结尾。也许显而易见的是程序做了什么,什么时候崩溃,也许不是。在后一种情况下:在这里发布最后一行。