私はサーバーとの通信にPOSIX TCP/IP関数を使用するCアプリケーションを開発中です。現在、接続が予期せず終了したときにアプリケーションがどのように応答するかを確認するためにいくつかのテストを行っています。TCP/IP接続を終了した後にPOSIXの "write"関数を使用すると、アプリケーションがクラッシュします - なぜですか?
メイン労役場の機能を以下に示します。
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;
}
任意の助けが不足しているエラーチェック@RemyLebeauが言及にさらに
書き込み呼び出しの受信者がいない場合、プロセスはSIGPIPEによって強制終了されるはずです。そのシグナルのシグナル処理をSIG_IGに設定してください。シグナルの代わりにEPIPEエラー番号を取得し始めるべきです。 – PSkocik
'socket()'や 'select()'でエラーチェックをしていないので、 'connect()'のエラーチェックが間違っています。 'm_sockfd'が非ブロックの場合、' connect() 'は-1を返し、' errno'は 'EINPROGRESS'を返します。 'ERR_NET_CONNECT_FAILED_IMMEDIATELY'を返す前にそれをチェックする必要があります。 'SO_ERROR'の取得は、取得するエラーコードがある場合にのみ有効です。したがって、' getsockopt() 'を呼び出す前に' select() 'が成功していることを確認してください。 –
@PSkocik:他のオプションには、1) 'write()'の代わりに 'send()'を使って 'MSG_NOSIGNAL'フラグを指定するか、' 2)setsockopt()を使って 'SO_NOSIGPIPE'オプション。これらのオプションをサポートするプラットフォームでは、つまり。 –