我正在使用POSIX TCP/IP函數與服務器進行通信的C應用程序。我正在做一些測試,看看應用程序在連接意外關閉時如何響應。殺死我的TCP/IP連接後使用POSIX「寫」功能崩潰我的應用程序 - 爲什麼?
主要習藝功能如下所示:
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;
}
此功能按預期工作時,我有與服務器的連接良好。但是,在終止連接後調用這個函數會使我的應用程序崩潰。
理想情況下,我希望寫函數返回一個錯誤,指出寫入失敗。這將允許我處理錯誤並將我的程序轉換到適當的狀態。但是,這不是發生了什麼。
我很好奇爲什麼這個函數調用會導致應用程序崩潰。我有些想,這可能是一個問題,其中函數調用沒有鎖定,然後它的引用指針變成'壞',導致分段錯誤。
這是我如何配置我的插座:
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;
}
任何幫助,將不勝感激
如果沒有接收者進行寫入調用,那麼您的進程應該被SIGPIPE殺死。將信號的信號處理設置爲SIG_IG,並且您應該開始獲取EPIPE errno錯誤代替信號。 – PSkocik
你在'socket()'或'select()'上根本沒有做任何錯誤檢查,而你在connect()方面的錯誤檢查是錯誤的。如果'm_sockfd'是非阻塞的,'connect()'將返回-1,'errno'將是'EINPROGRESS'。在返回'ERR_NET_CONNECT_FAILED_IMMEDIATELY'之前,您需要檢查。並且檢索'SO_ERROR'只是有一個錯誤代碼才能檢索,所以在調用'getsockopt()'之前確保'select()'成功。 –
@PSkocik:其他選項包括1)使用'send()'而不是'write()',這樣你就可以指定'MSG_NOSIGNAL'標誌,和/或2)使用'setsockopt()'啓用'SO_NOSIGPIPE'選項。在支持這些選項的平臺上,就是這樣。 –