本地socket的select用法

2021-08-03 09:40:58 字數 4077 閱讀 6161

client端

#include #include #include #include #include #include #include #include #include #include #include #include #define maxline 5

#define serv_port 6000

//!> 注意輸入是由stdin,接受是由server傳送過來

//!> 所以在client端也是需要select進行處理的

void send_and_recv( int connfd )

//!> if 連線口有資訊

if(fd_isset( connfd, &rset )) //!> if 連線埠有資訊

else if( n== -1 )

else

}//!> if 有stdin輸入

if(fd_isset( fileno( fp ), &rset )) //!> if 有輸入

else

for(i=0; i<5; i++) //測試,連續發五次,看server的返回情況

memset(send, 0, sizeof( send ) );

} }}}

int main( int argc, char ** argv )

//!> 建立套接字

if( ( connfd= socket( af_unix, sock_stream, 0 ) ) == -1 )

//!> 套接字資訊

// bzero(&servaddr, sizeof(servaddr));

servaddr.sun_family = af_unix;

strcpy(servaddr.sun_path,"selectfile");

// servaddr.sin_port = htons(serv_port);

// inet_pton(af_inet, argv[1],&servaddr.sin_addr);

//!> 鏈結server

if( connect(connfd, ( struct sockaddr * )&servaddr, sizeof( servaddr ) ) < 0)

//!>

//!> send and recv

send_and_recv( connfd );

//!>

close(connfd );

printf("exit\n");

return 0;

}

這個**有個地方需要注意:send[lens-1]= '\0';這一句讓我測試的時候吃了點苦頭,我定義的資料大小為5位元組,但我每次傳送3位元組資料的時候,server端可以正常返回,但傳送4位元組或5位元組的時候,server只返回前三個位元組,舉個例子,我輸入123,client會連續傳送五次123,server也給返回五次123,;如果我輸入12345,client傳送五次123,server返回五次123,但馬上我又按下回車,這時client會先連續發五次5,然後再發五次0,server端給回五個5,卻不是分五次回(兩次、三次?次數不一定,很是鬱悶),我認為這是緩衝區堆積的原因導致的(若果認識錯誤請指摘,謝謝)。

server端

#include #include #include #include #include #include #include #include #include #include #include #define buf_len 3

#define serv_port 6000

#define fd_size 100

#define max_back 100

#define soc_fd "selectfile"

int main( int argc, char ** argv )

//!>

//!> 下面是介面資訊

// bzero(&servaddr, sizeof( servaddr ) );

servaddr.sun_family = af_unix;

strcpy(servaddr.sun_path, soc_fd);

=htonl( inaddr_any);

// servaddr.sin_port = htons( serv_port );

//!>

//!> 繫結

if( bind(listenfd, ( struct sockaddr * )&servaddr, sizeof(servaddr ) ) == -1 )

//!>

//!> 監聽

if( listen(listenfd, max_back ) == -1 )

//!> 當前最大的感興趣的套接字fd

maxfd =listenfd; //!> 當前可通知的最大的fd

maxi =-1; //!> 僅僅是為了client陣列的好處理

for( i = 0;i < fd_size; i++) //!> 首先置為全-1

fd_zero(&allset); //!> 先將其置為0

fd_set(listenfd, &allset );

//!> 說明當前我對此套接字有興趣,下次select的時候通知我!

while( 1)

if( nready<= 0) //!> if 所有的感興趣的沒有就接著回去select

if(fd_isset( listenfd, &rset )) //!> if 是監聽介面上的「來電」

for( i = 0;i < fd_size; i++) //!> 注意此處必須是迴圈,剛開始我認

//!> 為可以直接設定乙個end_i來直接處

//!> 理,實質是不可以的!因為每個套接

}if( i ==fd_size ) //!> the last one

//!> listen的作用就是向陣列中加入套接字!

fd_set(connfd, &allset); //!> 說明現在對於這個連線也是感興趣的!

//!> 所以加入allset的陣容

if( connfd> maxfd) //!> 這個還是為了解決亂七八糟的陣列模型

//!> 的處理

if( i> maxi) //!> 同上

}//!> 下面就是處理資料函式( 其實說本質的select還是序列 )

for( i = 0;i <= maxi; i++) //!> 對所有的連線請求的處理

if( n == 0)

buf[n]= '\0';

printf("server recv: %s\n", buf);

if( strcmp(buf, "q" ) == 0) //!> 客戶端輸入「q」退出標誌

printf("server send : %s\n", buf);

write(sockfd, buf, n); //!> 讀出來的寫進去

printf("\n");

memset( buf,0, sizeof( buf )); //!> 此步重要,不要有時候出錯}}

}}

return 0;

}

server端也有改動:sleep(1);有人會說,select的用法就是要讓訊息立馬返回,不阻塞執行緒,但這裡是因為我的這個小demo在client端有個for迴圈(連續傳送五次資料),上面也說了,當傳送快於接收,緩衝區堆積,還有,網路(本地感覺也一樣,可以把server端看作是一種網路服務端,總感覺這麼理解怪怪的,希望有高手能告訴我一下應該怎麼解釋比較正確)寫函式是不負責將資料全部寫完之後再返回的。基於以上兩點,我就加了sleep,如果不加,client連續發五次訊息(假設是123),server會給回5個123,但不一定是分五次回,有可能是兩次、三次或五次等。

最後,推薦乙份資料,《linux程式設計(第4版)》,其實第幾版無所謂,內容差不多,這本資料的第15章套接字,裡面很詳細的介紹了socket的用法,建議想要了解socket的兄弟們去看下,最後的最後,歡迎各路大神指摘我的部落格,有錯改之才能進步,謝謝。

Socket程式設計之Select

select在socket程式設計中還是比較重要的,可是對於初學socket的人來說都不太愛用select寫程式,他們只是習慣寫諸如connect accept recv或recvfrom這樣的阻塞程式 所謂阻塞方式block,顧名思義,就是程序或是執行緒執行到這些函式時必須等待某個事件的發生,如果...

socket程式設計之select

linux程式設計之select select作用是 在一段指定的時間內,監聽使用者感興趣的檔案描述符上可讀 可寫和異常等事件。1 socket阻塞模式 通常在socket程式設計中,我們習慣於寫connect accept recv recvfrom這樣的阻塞程式。如果事件不發生,程式就一直阻塞在...

Socket超時設定 select 的妙用

阻塞與非阻塞 在 server 進入 listen 狀態之後,我們下面分別討論兩種實現方法 1.fcntl 方法 對乙個檔案描述符指定的檔案或裝置,有兩種工作方式 阻塞與非阻塞,阻塞的意思是指,當試圖對該檔案描述符進行讀寫時,如果當時沒有東西可讀,或者暫時不可寫,程式就進入等待狀態,直到有東西可讀或...