(1)connect描述
定義函式:
int connect (int sockfd,struct sockaddr * serv_addr,int addrlen);
connect函式通常用於客戶端建立tcp連線。
返回值:
成功則返回0,失敗返回-1,錯誤原因存於errno中。
錯誤**:
ebadf 引數sockfd 非合法socket處理**
efault 引數serv_addr指標指向無法訪問的記憶體空間
enotsock 引數sockfd為一檔案描述詞,非socket。
eisconn 引數sockfd的socket已是連線狀態
econnrefused 連線要求被server端拒絕。
etimedout 企圖連線的操作超過限定時間仍未有響應。
enetunreach 無法傳送資料報至指定的主機。
eafnosupport sockaddr結構的sa_family不正確。
ealready socket為不可阻塞且先前的連線操作還未完成。
(2)socket中連線過程比較
connect是套接字連線操作,connect操作之後代表對應的套接字已連線,udp協議在建立套接字之後,可以同多個伺服器端建立通訊,而tcp協議只能與乙個伺服器端建立通訊,tcp不允許目的位址是廣播或多播位址,udp允許。當然udp協議也可以像tcp協議一樣,通過connect來指定對方的ip位址、埠。
udp協議經過connect之後,在通過sendto來傳送資料報時不需要指定目的位址、埠,如果指定了目的位址、埠,那麼會返回錯誤。通過udp協議可以給同乙個套接字指定多次connect操作,而tcp協議不可以,tcp只能指定一次connect操作。udp協議指定第二次connect操作之後會先斷口第一次的連線,然後建立第二次的連線。
(3)客戶端在建立同伺服器端的連線過程
第一步都會通過socket建立連線套接字;
第二步通過bind來繫結本地位址、本地埠,當然繫結操作可以不用指定;
對於udp協議:若未指定繫結操作,那麼可以通過下面connect操作來由核心負責套接字的繫結操作,若
connect又未指定,那麼繫結操作只好通過套接字的寫操作(sendto、sendmsg)來指定目的位址、埠,這時
套接字本地位址不會指定,為通配位址,而本地埠由核心指定,第一次sendto操作之後,插口的本地埠經
過核心指定之後就不會更改。
對於tcp協議:若未指定繫結操作,可以通過下面connect操作來由核心負責套接字的繫結操作。核心會根
據套接字中的目的位址來判斷外出介面,然後指定該外出介面的ip位址為插口的本地位址。connect操作對於tcp
協議的客戶端是必不可少的,必須指定。
(4)非阻塞的 socket connect
非阻塞模式有3種用途
1.三次握手同時做其他的處理。connect要花乙個往返時間完成,從幾毫秒的區域網到幾百毫秒或幾秒的廣域網。這段時間可能有一些其他的處理要執行,比如資料準備,預處理等。
2.用這種技術建立多個連線。這在web瀏覽器中很普遍.
3.由於程式用select等待連線完成,可以設定乙個select等待時間限制,從而縮短connect超時時間。多數實現中,connect的超時時間在75秒到幾分鐘之間。有時程式希望在等待一定時間內結束,使用非阻塞connect可以防止阻塞75秒,在多執行緒網路程式設計中,尤其必要。 例如有乙個通過建立執行緒與其他主機進行socket通訊的應用程式,如果建立的執行緒使用阻塞connect與遠端通訊,當有幾百個執行緒併發的時候,由於網路延遲而全部阻塞,阻塞的執行緒不會釋放系統的資源,同一時刻阻塞執行緒超過一定數量時候,系統就不再允許建立新的執行緒(每個程序由於程序空間的原因能產生的執行緒有限),如果使用非阻塞的connect,連線失敗使用select等待很短時間,如果還沒有連線後,執行緒立刻結束釋放資源,防止大量執行緒阻塞而使程式崩潰。
在乙個 client/server模型的網路應用中,客戶端的呼叫序列大致如下:
socket -> connect -> recv/send -> close
其中socket沒有什麼可疑問的,主要是建立乙個套接字用於與服務端交換資料,並且通常它會迅速返回,此時並沒有資料通過網絡卡傳送出去,而緊隨其後的connect函式則會產生網路資料的傳送,tcp的三次握手也正是在此時開始,connect會先傳送乙個syn包給服務端,並從最初始的closed狀態進入到syn_sent狀態,在此狀態等待服務端的確認包,通常情況下這個確認包會很快到達,以致於我們根本無法使用netstat命令看到syn_sent狀態的存在,不過我們可以做乙個極端情況的模擬,讓客戶端去連線乙個隨意指定伺服器(如ip位址為88.88.88.88),因為該伺服器很明顯不會反饋給我們syn包的確認包(syn ack),客戶端就會在一定時間內處於syn_sent狀態,並在預定的超時時間(比如3分鐘)之後從connect函式返回,connect呼叫一旦失敗(沒能到達established狀態)這個套接字便不可用,若要再次呼叫connect函式則必須要重新使用socket函式建立新的套接字。
下面結合例項分析,客戶端**如下:
[cpp]view plain
copy
/*** client.c
** tcp client program, it is a ****** example only.
* writen by: zhou jianchun
* date: 2011.08.11
** compiled with: gcc -o client client.c
* tested on: ubuntu 11.04 lts
* gcc version: 4.5.2**/
#include
#include
#include
#include
#include
#include
#include
#include
#define server_port 20000
void usage(char *name)
int main(int argc, char **argv)
if((client_fd = socket(af_inet, sock_stream, 0)) < 0)
srand(time(null));
bzero(&client_addr, sizeof(client_addr));
client_addr.sin_family = af_inet;
client_addr.sin_addr.s_addr = htons(inaddr_any);
bzero(&server_addr, sizeof(server_addr));
server_addr.sin_family = af_inet;
inet_aton(argv[1], &server_addr.sin_addr);
server_addr.sin_port = htons(server_port);
if(connect(client_fd, (struct sockaddr*)&server_addr, socklen) < 0)
return 0;
}
編譯完成之後執行:
[cpp]view plain
copy
zhou@neptune:~/data/source$ ./client 88.88.88.88
此時程式會在connect函式中阻塞等待,約180秒之後輸出:
[cpp]view plain
copy
can not connect to 88.88.88.88, exit!
connection timed out
此刻connect的返回值為etimeout。
在此過程中我們可以用netstat命令查詢連線狀態:
[cpp]view plain
copy
zhou@neptune:~/data/source$ sudo netstat -natp |grep 20000
tcp 0 1 192.168.0.4:44203 88.88.88.88:20000 syn_sent 5954/client
可以看到此時的tcp連線狀態為syn_sent,也就意味著傳送了syn包之後一直未得到服務端回饋syn ack包。
[cpp]view plain
copy
zhou@neptune:~/data/source$ ./client 192.168.0.4
can not connect to 192.168.0.4, exit!
connection refused
因為我的機器上並沒有跑在指定埠(20000)上監聽的服務端程式,所以這個連線直接被協議棧拒絕(通過傳送rst型別的tcp包),connect立刻返回,返回值為econnrefused。
再來看看去連線同一區域網中一台不存在的主機時的情形,比如這台想象的主機的ip位址為192.168.0.188:
[cpp]view plain
copy
zhou@neptune:~/data/source$ ./client 192.168.0.188
can not connect to 192.168.0.188, exit!
no route to host
因為本地區域網中的該主機並不存在,arp請求得不到回應,閘道器會回應主機不可達的icmp報文,connect返回ehostunreach。
至此connect函式的分析就結束了,由於本人水平有限,部落格中的不妥或錯誤之處在所難免,殷切希望讀者批評指正。同時也歡迎讀者共同**相關的內容,如果樂意交流的話請留下您寶貴的意見,謝謝。
Linux網路程式設計之connect函式分析
在乙個 client server模型的網路應用中,客戶端的呼叫序列大致如下 socket connect recv send close 其中socket沒有什麼可疑問的,主要是建立乙個套接字用於與服務端交換資料,並且通常它會迅速返回,此時並沒有資料通過網絡卡傳送出去,而緊隨其後的connect函...
Linux網路程式設計connect 函式的使用
在乙個 client server模型的網路應用中,客戶端的呼叫序列大致如下 socket connect recv send close 其中socket沒有什麼可疑問的,主要是建立乙個套接字用於與服務端交換資料,並且通常它會迅速返回,此時並沒有資料通過網絡卡傳送出去,而緊隨其後的connect函...
網路程式設計 非阻塞connect詳解
一 為什麼使用非阻塞connect tcp連線的建立涉及乙個在三路握手過程,阻塞的connect一直等到客戶收到自己的syn的ack才返回,這需要至少乙個rtt時間,rtt時間波動很大從幾毫秒到幾秒。而且在沒有響應時,會等待數秒再次傳送,詳見tcpv2第828頁 總共75秒到幾分鐘的connect超...