在 Linux 中通过 Socket 发送数据而没有连接时崩溃

Posted

技术标签:

【中文标题】在 Linux 中通过 Socket 发送数据而没有连接时崩溃【英文标题】:Crash when sending data without connection via Socket in Linux 【发布时间】:2013-10-10 22:55:08 【问题描述】:

我正在使用C语言在Linux中使用命令通过socket发送数据

send(ServerSocket, cSendBuff, strlen(cSendBuff), 0);

程序是:

    创建套接字 连接到服务器 while(条件):发送数据

我在Linux环境下运行这个程序,如果是连接的,没有问题。但是为了在运行时处理失败的连接,我检查了一些情况并得到了如下结果:

案例一:

    创建套接字:未创建(注释掉创建函数) 连接到服务器:无连接(注释掉连接功能) 发送数据 --> 失败(返回 -1)但没有崩溃

案例 2:

    创建套接字:成功 连接到服务器:失败甚至没有连接(注释掉 连接函数) 发送数据 --> 崩溃

然后,我尝试了 3 个不同的套接字值 WITHOUT 连接到服务器

案例 3:

    ServerSocket = -1 --> 发送数据:失败 ServerSocket = 0 --> 发送数据:失败 ServerSocket = 4 --> 发送数据:崩溃

如果发送失败,这是正确的,但我不明白为什么在其他情况下我会崩溃。我尝试使用 Windows 但没问题,Linux 和 Windows 之间有什么不同吗?是否有意义?我只想打开套接字并连接到服务器一次,然后发送数据一千次,所以如果在这种情况下“崩溃”是有意义的,如果连接失败,我该如何解决这个问题?感谢您的宝贵时间。

这是案例 2(通过停止服务器以测试连接失败的情况,连接失败):

ServerSocket = socket(AF_INET,SOCK_STREAM,IPPROTO_IP) ;
...
iResult = connect(ServerSocket,(struct sockaddrx *)&server , sizeof(server));
iResult = send(ServerSocket, cSendBuff, strlen(cSendBuff), 0);
if(iResult<0)
...

这是案例 3:

    //ServerSocket = socket(AF_INET,SOCK_STREAM,IPPROTO_IP) ;
    ...
    //iResult = connect(ServerSocket,(struct sockaddrx *)&server , sizeof(server));
    ServerSocket = 0;
    iResult = send(ServerSocket, cSendBuff, strlen(cSendBuff), 0);
    log();
    ServerSocket = -1;
    iResult = send(ServerSocket, cSendBuff, strlen(cSendBuff), 0);
    log();
    ServerSocket = 4;
    iResult = send(ServerSocket, cSendBuff, strlen(cSendBuff), 0);
    log();
    if(iResult<0)
    ...

【问题讨论】:

你能显示一些代码吗? 请不要在 cmets 中发布代码。将其编辑到您的问题中。您可以亲眼看到,如果没有格式化,这是您在 cmets 中无法做到的,它是完全难以辨认的。我在此代码中没有看到任何错误检查,因此无法说出“失败”或“崩溃”的确切含义。请说清楚。并请发布所有相关代码。 那是我的情况3,在日志中,ServerSocket = 4之后程序崩溃 【参考方案1】:

您的程序不会 崩溃

它收到SIGPIPE 信号,因为套接字的本地端已关闭。阅读man 2 send,尤其是EPIPE 错误案例。 (因此,准确地说,您的程序由于未处理的SIGPIPE 信号而终止。)

正如man 7 signal 手册页所说,SIGPIPE 的默认处置是终止进程。为避免终止,请设置SIGPIPE 信号处理程序,或使用send(socket, buffer, length, MSG_NOSIGNAL)

不要将 Windows 用作衡量标准。这不是一个理智的方法。你有更好的,实际上可靠的文档可用。 Linux man-pages 项目是 C 库文档 (section 3) 的最佳来源之一。尽管它专注于 Linux 和 GNU C 库,但每个页面都有一个 符合 部分,它告诉您该功能何时何地可用。

以上链接指的是最新的网页,但您也可以在命令行上使用man 2 sendman 7 signal 来浏览相同的信息。网页比发行版更新,但该项目仅包含标准手册页,而不包括由应用程序安装的手册页或您可能拥有的额外库。

问题?

【讨论】:

好的,感谢您的评论。所以可能是因为在iResult = send(ServerSocket, cSendBuff, strlen(cSendBuff), 0); 中使用了 0。我应该改成iResult = send(ServerSocket, cSendBuff, strlen(cSendBuff), MSG_NOSIGNAL);。对吗? @hoangsonvnu:如果您不想要SIGPIPE 信号(这会导致您的程序终止——您认为是“崩溃”),那么请使用MSG_NOSIGNAL 标志。来吧,这并不难。阅读链接的参考文献!【参考方案2】:

案例 2.3:这应该失败,我的意思是它应该返回 -1 并带有 errno. 的伴随值你没有说明“失败”或“崩溃”是什么意思,, ' 所以无法进一步评论。

案例 3: 除非 FD 0 或 4 恰好是一个套接字,否则这些都应该失败。

我不知道你为什么要测试这些。 “连接失败”与从未连接过的套接字完全不同。 “连接失败”表现为来自 send(), recv(), 和朋友的 -1 返回,伴随的值为 errno 而不是 EAGAIN/EWOULDBLOCK. 您不能发送到未连接的 TCP 套接字,它应该您的代码甚至无法尝试它。如果是,你的错误处理代码路径不正确。

【讨论】:

Fail 表示Return (-1),根据我的理解是有道理的。我知道如果没有连接我们无法发送数据,但我必须处理真实系统中的所有情况。连接后,我通过一千条send()命令发送数据,在其运行过程中,无论出于何种原因,连接都可能随时丢失。在这种情况下,我崩溃了,而不是继续运行 你得到了 what 'crash?'什么症状?而且您当然不必处理在套接字从未连接的情况下发送的情况。您的代码应该使它不可能。这都是没有意义的。您的代码只需对send()recv() 返回-1 等的真实案例做出正确反应,如我的回答。 程序崩溃,它停止,不再运行,没有返回任何东西。当然,我在通过if(iResult==-1) 发送后做出反应然后......但是如果发生崩溃,我什至无法在发送后获得值 -1。正如我所说,程序在send() 之后立即停止,它无法运行下一个命令,无法返回 -1 进行检查。这才是重点。所以我想知道为什么会这样,据我所知这没有意义 没有信号?例如没有SIGSEGV?或SIGPIPE? 没有核心转储?你不打电话给exit()abort()assert()?这是不合理的。

以上是关于在 Linux 中通过 Socket 发送数据而没有连接时崩溃的主要内容,如果未能解决你的问题,请参考以下文章

在 Erlang 中通过 tcp 套接字发送元组

JAVA中通过socket得到的字符串是乱码

在PHP中通过TCP发送XML EPP请求

《asyncio 系列》8. 在 asyncio 中通过流(StreamReaderStreamWriter)来实现 TCP 请求的发送与接收

如何在Linux命令行中通过SMTP服务器发送电子邮件

在python中通过调制解调器发送wav声音