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 方法 對乙個檔案描述符指定的檔案或裝置,有兩種工作方式 阻塞與非阻塞,阻塞的意思是指,當試圖對該檔案描述符進行讀寫時,如果當時沒有東西可讀,或者暫時不可寫,程式就進入等待狀態,直到有東西可讀或...