send() 使我的程序崩溃

发布于 2024-11-09 23:15:48 字数 1829 浏览 1 评论 0原文

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

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

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 呢?

I'm running a server and a client. i'm testing my program on my computer.

this is the funcion in the server that sends data to the client:

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;
}

when the client exits it sends to the server "BYE" and the server is replying it with the above function. I connect the client to the server (its done on one computer, 2 terminals) and when the client exits the server crashes - it never prints the 15.
any idea why ? any idea how to test why?

thank you.

EDIT: this is how i close the client:

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);
}

btw, if i skipp this code, meaning just leave the close(_sockfd) without notifying the server everything is ok - the server doesn't crash.

EDIT 2: this is the end of 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 +++

broken pipe can kill my program?? why not just return -1 by send()??

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

好听的两个字的网名 2024-11-16 23:15:48

您可能需要在标志中指定 MSG_NOSIGNAL

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

You may want to specify MSG_NOSIGNAL in the flags:

int nbytes = send(fd,msg.c_str(), msg.size(), MSG_NOSIGNAL);
温柔嚣张 2024-11-16 23:15:48

您之所以收到 SIGPIPE,是因为 Unix 中的一项“功能”会在尝试在远程对等方已关闭的套接字上发送数据时引发 SIGPIPE。由于您不处理信号,因此会调用默认信号处理程序,并且它会中止/崩溃您的程序。

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

#include <signal.h>

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

You're getting SIGPIPE because of a "feature" in Unix that raises SIGPIPE when trying to send on a socket that the remote peer has closed. Since you don't handle the signal, the default signal-handler is called, and it aborts/crashes your program.

To get the behavior your want (i.e. make send() return with an error, instead of raising a signal), add this to your program's startup routine (e.g. top of main()):

#include <signal.h>

int main(int argc, char ** argv)
{
   [...]
   signal(SIGPIPE, SIG_IGN); 
爱本泡沫多脆弱 2024-11-16 23:15:48

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

链接

此套接字已连接,但
连接现已断开。在这个
情况下,send 生成一个 SIGPIPE 信号
第一的;如果该信号被忽略或
被阻止,或者如果它的处理程序返回,
然后发送失败并显示 EPIPE。

Probably the clients exits before the server has completed the sending, thus breaking the socket between them. Thus making send to crash.

link

This socket was connected but the
connection is now broken. In this
case, send generates a SIGPIPE signal
first; if that signal is ignored or
blocked, or if its handler returns,
then send fails with EPIPE.

吻泪 2024-11-16 23:15:48

如果客户端在服务器第二次发送之前退出,并且连接未正确处理,则您的服务器将持续挂起,这可能会引发崩溃。

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

If the client exits before the second send from the server, and the connection is not disposed of properly, your server keeps hanging and this could provoke the crash.

Just a guess, since we don't know what server and client actually do.

梦里南柯 2024-11-16 23:15:48

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

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

如果定义 int len = msg.size(); 会发生什么?

I find the following line of code strange because you define int len = msg.size()+1;.

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

What happens if you define int len = msg.size();?

半城柳色半声笛 2024-11-16 23:15:48

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

strace -f -o strace.out ./server

然后查看日志文件的末尾。也许程序做了什么以及何时崩溃是显而易见的,也许不是。在后一种情况下:在此处发布最后几行。

If you are on Linux, try to run the server inside strace. This will write lots of useful data to a log file.

strace -f -o strace.out ./server

Then have a look at the end of the log file. Maybe it's obvious what the program did and when it crashed, maybe not. In the latter case: Post the last lines here.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文