一. 服務器端
1.加載WInSock庫
因爲WinSock服務是通過動態鏈接庫WinSock DLL實現的,所以調用WinSock函數前,需要加載WinSock庫啓動服務。
int WSAStart( WORD wVersion, LPWSADATA lpWSAData);
wVersion 指定加載的WinSock版本號,一般使用MAKEWORD(X,Y); X指副版本號,Y指主版本號;
LPWSADATA 結構包含了加載的WinSOck庫的信息,可以不用到。
返回值爲0,表示成功。
例:
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);
2.服務器進程創建用於監聽的套接字
服務器進程總是先於客戶端進程啓動。
SOCKET socket(int af , int type, int protocol);
af ---- 網絡地址類型,一般爲AF_INET;
type ------套接字類型,SOCK_STREAM爲流套接字,SOCK_DGRAM爲數據報套接字;
protocol---網絡協議,一般取0;
返回值SOCKET爲所創建的套接字的句柄。
例:SOCKET sockSrv= socket(AF_INET, SOCK_STREAM, 0);
3.綁定套接字
int bind(SOCKET s, const struct sockaddr* name, int namelen);
s---要綁定的套接字句柄;
namelen---name的字節數;
sockaddr----一般用sockaddr_in
sockaddr_in(在netinet/in.h中定義):
struct sockaddr_in {
short int sin_family; /* Address family */
unsigned short int sin_port; /* Port number */
struct in_addr sin_addr; /* Internet address */
unsigned char sin_zero[8]; /* Same size as struct sockaddr */
}
sin_famil-----必須爲AF_INET;
sin_port------指定服務器端口;
sin_addr----IP地址,(設爲INADDR_ANY,以便監聽每個網絡接口);
sin_zero---無需設置;
例:
SOCKADDR_IN addrSrv;
addrSrv.sin_family = AF_INET;
addrSrv.sin_port = htons(5099); //1024以上的端口號
addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
int retVal = bind(sockSrv, (LPSOCKADDR)&addrSrv, sizeof(SOCKADDR_IN));
4.監聽
int listen(SOCKET s, int backlog);
backlog---等待連接的最大隊列長度;
5.等待請求來到
SOCKET accept(SOCKET s, struct sockaddr * addr , int * addrlen);
s---監聽套接字句柄;
addr --存儲客戶端ip信息;
addrlen --- addr長度;
返回套接字句柄,該套接字用於和客戶端連接。
accept函數無連接請求是阻塞,有請求才處理。
6.send/recv;
7.closesocket
8.釋放WinSock資源
關閉套接字後,終止使用WInSock DLL,釋放資源。
int WSACleanup(void); 若成功返回0.
二:客戶端
1.加載庫
2.創建套接字
3.connect
int connect(SOCKET s, const struct sockaddr FAR* name, int namelen);
name---指定服務器進程IP地址和端口。
4.recv/send
。。。。。