我正在开发一个使用POSIX TCP / IP功能与服务器通信的C应用程序。我正在进行一些测试,看看当连接意外关闭时应用程序如何响应。
主要的工作室功能如下所示:
uint32_t netWriteMsg(uint8_t * pmsg, size_t msg_size)
{
if(write(m_sockfd, pmsg, msg_size) < msg_size)
return ERR_NET_NOT_ALL_BYTES_SENT;
return ERR_NONE;
}
当我与服务器建立良好连接时,此功能可以正常工作。但是,在终止连接后调用此函数会导致我的应用程序崩溃。
理想情况下,我希望write函数返回一个错误,指示写入失败。这将允许我处理错误并将我的程序转换到适当的状态。但是,这不是发生的事情。
我很好奇为什么这个函数调用会使应用程序崩溃。我有点认为这可能是函数调用没有锁定的问题,然后它引用的指针变得“坏”,导致分段错误。
以下是我配置套接字的方法:
uint32_t netConnect()
{
/* locals */
struct sockaddr_in serv_addr;
fd_set fdset_sock; // only 1 file descriptor (socket fd) will be placed in this set
fd_set fdset_empty;
struct timeval time = {NET_TIMEOUT_CONNECT, 0};
int sock_error;
socklen_t optlen;
int error = ERR_NONE;
/* obtain socket file descriptor and set it to non-blocking */
m_sockfd = socket(AF_INET, SOCK_STREAM, 0);
memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(PORT_NO);
inet_pton(AF_INET, IP_ADDR, &(serv_addr.sin_addr.s_addr));
/* attempt to connect */
error = connect(m_sockfd, &serv_addr, sizeof(serv_addr));
if(error) return ERR_NET_CONNECT_FAILED_IMMEDIATELY;
select(m_sockfd, &fdset_empty, &fdset_sock, &fdset_empty, &time); // blocks until socket is good or timeout occured
error = getsockopt(m_sockfd, SOL_SOCKET, SO_ERROR, &sock_error, &optlen);
if(error) return ERR_NET_COULD_NOT_GET_SOCKET_OPTION;
if(sock_error)
return ERR_NET_CONNECT_ATTEMPT_TIMEOUT;
m_is_connected = 1;
return ERR_NONE;
}
任何帮助将不胜感激
答案 0 :(得分:1)
除了提到的遗漏错误检查@RemyLebeau之外,您也没有错误检查write()
本身:
if(write(m_sockfd, pmsg, msg_size) < msg_size)
return ERR_NET_NOT_ALL_BYTES_SENT;
这里你忽略了它返回-1的可能性,在这种情况下你应该调用perror()
或用strerror()
构造一个错误消息字符串并打印它,和关闭套接字,和告诉来电者他没有继续写作。
您还需要将SIGPIPE设置为SIG_IGNORE或其他任何内容,以便EPIPE写入错误不会导致SIGPIPE信号。
所有这些ERR_NET_COULD_NOT_GET_SOCKET_OPTION的东西都很糟糕。您应该返回实际的errno
值,或者至少打印它,而不仅仅是在getsockopt()
情况下,而是在所有错误情况下。
你正在以阻止模式进行connect()
。因此,以下select()
完全没有意义。