在 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 send
、man 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 发送数据而没有连接时崩溃的主要内容,如果未能解决你的问题,请参考以下文章
《asyncio 系列》8. 在 asyncio 中通过流(StreamReaderStreamWriter)来实现 TCP 请求的发送与接收