Socket 讀寫處理及連線斷開的檢測

2021-08-19 08:07:15 字數 3401 閱讀 5347

作為程序間通訊及網路通訊的一種重要技術,在實際的開發中,socket程式設計是經常被用到的。關於socket程式設計的一般步驟,這裡不再贅述,相關資料和文章很多,google/baidu即可。

本文主要是**如何更好地進行socket讀寫處理,以及如何檢測連線斷開。

首先,有以下幾點需要注意:

對於全雙工的socket,同時讀寫是沒問題的。比如,乙個socket程式有兩個執行緒,乙個執行緒對socket進行讀操作(recv/read),乙個執行緒對socket進行寫操作(send/write),這裡是不需要進行互斥操作或做臨界區保護的。

在unix系統下, 對乙個對端已經關閉的socket呼叫兩次write,第二次將會生成sigpipe訊號,該訊號的預設處理動作是終止程序。為了防止在這種情況下導致程序退出,我們需要遮蔽該訊號的預設處理動作。有兩種方法,a) 在程式開頭呼叫signal(sigpipe, sig_ign),忽略sigpipe訊號的預設動作;b) 採用send函式的msg_nosignal標誌位,忽略sigpipe訊號。當然,雖然我們忽略了sigpipe,但errno還是會被設定為epipe的。因此,我們可以根據這點,按照我們的情況來進行相應的處理了。

對檔案描述符進行select/poll操作,a) 如果select/poll返回值大於0,此時進行recv/read,recv/read返回0,表明連線關閉; b)  recv/read返回-1,並且errno為econnreset、ebadf、epipe、enotsock之一時,也表明連線關閉。

對檔案描述符進行send/write操作,如果send/write返回-1,並且errno為econnreset、ebadf、epipe、enotsock之一時,也表明連線關閉。

下面是乙個demo程式,server端**(server.c)為:

#define _gnu_source#include 

#include

#include

#include

#include

#include

#include

#include

#include

#define unix_path_max 108

#define sock_path "/tmp/test.sock"

int sock_write(int fd, char* buf, int

len)

}else

if( res > 0

)else

if( res ==len ) }}

return

disconnect;

}void* write_handle(void*fd)

}int main(void

) unlink(sock_path);

memset(&address, 0, sizeof(struct

sockaddr_un));

address.sun_family =af_unix;

snprintf(address.sun_path, unix_path_max, sock_path);

if(bind(socket_fd, (struct sockaddr *) &address, sizeof(struct sockaddr_un)) != 0

)

if(listen(socket_fd, 0) != 0

)

while((connection_fd = accept(socket_fd, (struct sockaddr *) &address,&address_length)) > -1

)

}else

if( -1 ==cnt )

if( disconnect )

}else

if( cnt > 0

) #ifdef debug

if( 0 ==nbytes )

#endif

} }

#ifdef debug

else

if(res == -1

)

#endif

} close(connection_fd);

pthread_cancel(w_thread);

}close(socket_fd);

unlink(sock_path);

return0;

}

client端**(client.c)為:

#define _gnu_source#include 

#include

#include

#include

#include

#include

#include

#include

#define unix_path_max 108

#define sock_path "/tmp/test.sock"

int main(void

) memset(&address, 0, sizeof(struct

sockaddr_un));

address.sun_family =af_unix;

snprintf(address.sun_path, unix_path_max, sock_path);

if(connect(socket_fd, (struct sockaddr *) &address, sizeof(struct sockaddr_un)) != 0

)

#ifdef debug

printf(

"connect success!\n

");

#endif

#if 1pfd.fd =socket_fd;

pfd.events = pollin | pollhup |pollrdnorm;

pfd.revents = 0

; disconnect = 0

;

while(1

)

if(disconnect)

}else

if( 0 ==cnt)

}else

if( cnt > 0

) }}}

#endif

close(socket_fd);

socket_fd = -1

;#ifdef debug

printf(

"server disconnect!\n");

#endif

/*here sleep 5 seconds and re-connect.

*/sleep(5);

}return0;

}

關於socket判斷連線斷開並重連

關於socket判斷連線斷開並重連 以下是個執行緒函式 uint cmonitordlg threadfunction lpvoid pparam if connect s,struct sockaddr serv1,sizeof serv1 invalid socket else else if ...

socket程式設計 優雅的斷開連線shutdown

呼叫 close closesocket 函式意味著完全斷開連線,即不能傳送資料也不能接收資料,這種 生硬 的方式有時候會顯得不太 優雅 上圖演示了兩台正在進行雙向通訊的主機。主機a傳送完資料後,單方面呼叫 close closesocket 斷開連線,之後主機a b都不能再接受對方傳輸的資料。實際...

關於PHP中Socket連線及讀寫資料超時的問題

雖然php中對fsockopen 方法有連線socket的超時引數,但是沒有類似c中的連線成功後對資料的讀寫超時引數設定。沒關係,php中對stream提供了一系列的方法以防止超時 stream set blocking fp false 設定資料流為阻塞模式,以防止資料沒讀完就退出 如果模式為 f...