總的來說網絡程序是由兩個部分組成的--客戶端和服務器端.它們的建立步驟一般是:
服務器端 socket-->bind-->listen—>accept
客戶端 socket-->connect
在WINDOWS環境下使用SOCKET前需要初始化windows socket庫,否則socket()會返回SOCKET_ERROR(-1)
SOCKET socket(int domain, int type,int protocol)
- domain:說明我們網絡程序所在的主機採用的通訊協族(AF_UNIX和AF_INET等). AF_UNIX只能夠用於單一的Unix系統進程間通信,而AF_INET是針對Internet的,因而可以允許在遠程主機之間通信
- type:我們網絡程序所採用的通訊協議(SOCK_STREAM,SOCK_DGRAM等) SOCK_STREAM表明我們用的是TCP協議,這樣會提供按順序的,可靠,雙向,面向連接的比特流. SOCK_DGRAM 表明我們用的是UDP協議,這樣只會提供定長的,不可靠,無連接的通信.
- protocol:由於我們指定了type,所以這個地方我們一般只要用0來代替就可以了 下面是from WINSOCK.H的協議定義
eg:
sListen = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
int bind(int sockfd, struct sockaddr *my_addr, int addrlen)
- sockfd:是由socket調用返回的文件描述符.
- addrlen:是sockaddr結構的長度.
- my_addr:是一個指向sockaddr的指針. 在WINSOCK.H中有 sockaddr的定義 :
localaddr.sin_addr.s_addr = inet_addr(ipaddr);
localaddr.sin_family = AF_INET;
localaddr.sin_port = htons(portNum);
bind(s_ , (struct sockaddr*)&localaddr , sizeof(localaddr)) ;
由於客戶端不需要固定的端口號,因此不必調用bind(),客戶端的端口號由內核自動分配。如果服務器不調用bind(),內核會自動給服務器分配監聽端口,每次啓動服務器時端口號都不一樣,客戶端要連接服務器就會遇到麻煩。
int listen (SOCKET s, int backlog);
- s:bind後的SOCKET文件描述符
- backlog:設置請求排隊的最大長度.當有多個客戶端程序和服務端相連時, 使用這個表示可以介紹的排隊長度.(允許監聽多少個TCP連接)
- listen函數將bind的文件描述符變爲監聽套接字.出錯返回-1
e.g.
listen(sListen, 3);
SOCKET accept (SOCKET s, struct sockaddr *addr, int *addrlen);
- s:是listen後的SOCKET文件描述符
- addr,addrlen是用來給客戶端的程序填寫的,服務器端只要傳遞指針就可以了. bind,listen和accept是服務器端用的函數,accept調用時,服務器端的程序會一直阻塞到有一個客戶程序發出了連接. accept成功時返回最後的服務器端的文件描述符,這個時候服務器端可以向該描述符寫信息了. 失敗時返回-1
e.g.
sClient = accept(sListen, (struct sockaddr *)&client, &iaddrSize);