SOCKET基礎學習筆記

 PS:爲了區分SOCKET函數版本,Winsock2版本前加WSA前綴,例如:socket WSASocket;對採用Winsock 1的應用而言,必須有Wi n s o c k . h包容文件,而對使用Winsock 2的應用而言,則需要Winsock 2.h包容文件。
int WSAGetLastError(void);發生錯誤之後調用這個函數,就會返回所發生的特定錯誤的完整代碼。
一旦爲某種特定協議創建了套接字,就必須將套接字綁定到一個已知地址。
int bind(
SOCKET s; //希望在上面等待客戶機聯機的套接字
const struct sockaddr FAR* name; //地址緩衝區
int namelen;
);
SOCKET s;
struct sockaddr_in tcpaddr;
int port=5150;
s=socket(AF_INET,SOCK_STRAM,IPPROTO_TCP);
tcpaddr.sin_family=AF_INET;
tcpaddr.sin_port=htons(port);
tcpaddr.sin_addr.s_addr=htonl(INADDR_ADY);
bind(s,(SOCKADDR*)&tcpaddr,sizeof(tcpaddr));
b i n d函數的作用只是將一個套接字和一個
指定的地址關聯在一起。指示一個套接字等候進入連接的A P I函數則是l i s t e n
int listen(
SOCKET s,
int backlog //等待連接的最大個數
);
當我們都做好準備時,就可以用accept函數來接受連接
SOCKET accepy(
SOCKET s,
struct sockaddr FAR* addr,//發出連接請求的套接字信息
int FAR* addrlen //第二個參數的長度
);
a c c e p t會返回一個新的套接字描述符,它對應於已經接受的那個客戶機連接。對於該客戶機後續的所有操作,都應使用這個新套接字。至於原來那個監聽套接字,它仍然用於接受其他客戶機連接,而且仍處於監聽模式。
SOCKET WSAAccept(
SOCKET s,
struct sockaddr FAR* addr,
LPINT addrlen,
LPCONDITIONPROC lpfnCondition, //回調函數定義如下
DWORD dwCallbackData //?????
);
int CALLBACK ConditionFunc(
LPWSABUF lpCallerId, //連接實體的地址
LPWSABUF lpCallerData, //連接實體附帶的請求數據(一般不支持)
LPQOS lpSQOS, //獨立連接時需要的帶寬
LPQOS lpGQOS, //套接字組連接需要的帶寬(不支持)
LPWSABUF lpCalleeId, //客戶機連接的本地地址
LPWSABUF lpCalleeData, //可以作爲連接請求的一部分返回給客戶機(一般不支持)
GROUP FAR* g,//???????
DWORD dwCallbackData //?????????
);
typedef struct _WSABUF{
u_long len;
char FAR* buf;
}WSABUF,FAR* LPWSABUF;
connect函數和WSAConnect函數
int connect(
SOCKET s,
const struct sockaddr FAR* name,
int namelen
);
int WSAConnect(
SOCKET s,
const struct sockaddr FAR* name,
int namelen,
LPWSABUF lpCallerData, //發送給服務器的附加數據
LPWSABUF lpCalleeData,//服務器傳回的附加數據(不支持)
LPQOS lpSQOS, //套接字需要的網絡質量
LPQOS lpGQOS
);
數據收發沒有Unicode版本,所以經常用到WideCharToMultiByte把UNICODE轉換爲ASCII版本
int send(
SOCKET s,
const char FAR* buf,
int len,
int flags
);
l a g s可爲0、M S G _ D O N T R O U T E或M S G _ O O B。另外, f l a g s還可以是對那些標誌進行按位“或運算”的一個結果。M S G _ D O N T R O U T E標誌要求傳送層不要將它發出的包路由出去。
M S G _ O O B標誌預示數據應該被帶外發送(緊急數據)
int WSASend(
SOCKET s,
LPWSABUF lpBuffers, //發送的一組結構多用於分散集合I/O
DWORD dwBufferCount, //傳送的結構數
LPDWORD lpNumberOfBytesSent, //字節總髮送數
DWORD dwFlags,
LPWSAOVERLAPPED lpOverlapped, //用於重疊I/O
LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionROUTINE //用於重疊I/O
);
int recv(
SOCKET s,
char FAR* buf,
int len,
int flags
);
f l a g s參數可以是下面的值: 0、M S G _ P E E K或M S G _ O O BM S G _ P E E K會使有用的數據複製到所提供的接收端緩衝內,但是沒有從系統緩衝中將它刪除
int WSARecv(
SOCKET s,
LPWSABUF lpBuffers,
DWORD deBufferCount,
LPDWORD lpNumberOfBytesReceived,
LPDWORD lpFlags,
LPWSAOVERLAPPED lpOverlapped,
LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionROUTINE
);
M S G _ PA RT I A L標誌使用和出現的地方不同,其含義也不同。對面向消息的協議來說,這個標誌是W S A R e c v調用返回後設置的(如果因爲緩衝空間不夠導致整條消息未能在這次調用中返回的話)。這時,後面的W S A R e c v調用就會設置這個標誌M A S G _ PA RT I A L,直到整條消息返回,才把這個標誌清除。如果這個標誌當作一個輸入參數投遞,接收操作應該在一收到數據就結束,即使它收到的只是整條消息中的一部分。
int shutdown(
SOCKET s,
int how
); //用於從容關閉端口
h o w參數可以是下面的任何一個值: S D _ R E C E I V E、S D _ S E N D或S D _ B O T H。如果是
S D _ R E C E I V E,就表示不允許再調用接收函數。這對底部的協議層沒有影響。另外,對T C P套接字來說,不管數據在等候接收,還是數據接連到達,都要重設連接。儘管如此, U D P套接字上,仍然接受並排列接入的數據。如果選擇S E _ S E N D,表示不允許再調用發送函數。對T C P套接字來說,這樣會在所有數據發出,並得到接收端確認之後,生成一個F I N包。最後,如果指定S D _ B O T H,則表示取消連接兩端的收發操作。
無連接協議下
int recvfrom(
SOCKET s,
char FAR* buf,
int len,
int flags, //M S G _ O O B和M S G _ P E E K
struct sockaddr FAR* from,
int FAR* fromlen
);
int WSARecvFrom(
SOCKET s,
LPWSABUF lpBuffers,
DWORD dwBufferCount,
LPDWORD lpNumberOfBytesReceivd,
LPDWORD lpFlags, //0、M S G _ O O B、M S G _ P E E K或M S G _ PA RT I A L
struct sockaddr FAR* lpFrom,
LPINT lpFromlen,
LPWSAOVERLAPPED lpOverlapped,
LPWSAOVERLAPPED_COMPELTION_ROUTINE lpCompletionROUTINE
);
int sendto(
SOCKET s,
const char FAR* buf,
int len,
int flags,
const struct sockaddr FAR* to, //服務器目標地址
int tolen
):
int WSASendTo(
SOCKET s,
LPWSABUF lpBuffers,
DWORD dwBufferCount,
DWORD dwBufferCount,
LPDWROD lpNumberOfBytesSent,
DWORD dwFlags,
const struct sockaddr FAR* lpTo,
int iTolen,
LPWSAOVERLAPPED lpOverlapped,
LPWSAOVERLAPPED_CONPLETION_ROUTINE lpCompletionROUTINE
);
其他函數
獲得通信方的套接字地址信息,該信息是關於已建立連接的那個套接字的
int getpeername(                        
SOCKET s,
struct sockaddr FAR* name,
int FAR* namelen
);
指定套接字的本地接口的地址信息
getsockname(
SOCKET s,
struct sockaddr FAR* name,
int FAR* namelen
);
Tr a n s m i t F i l e
Tr a n s m i t F i l e是微軟專有的Wi n s o c k擴展,它允許從一個文件中傳輸高性能數據。這是非常有效的,因爲整個數據傳輸可在內核模式中進行。也就是說,如果你的應用從指定的文件中讀取一堆數據,然後用s e n d或W S A S e n d時,涉及到“用戶模式到內核模式傳輸”的發送調用就有若干個。有了Tr a n s m i t F i l e,整個讀取和發送數據的進程就可在內核模式中進行。該函數的定義如下:
BOOL TransmitFile(
SOCKET hSocket,
HANDLE hFile,
DWORD nNumberOfBytesToWrite, //要發送的文件大小,0爲全部
DWORD nNumberOfBytesPerSend, //以多大的數據塊進行發送,0爲默認
LPOVERLAPPED lpOverlapped,
LPTRASMIT_FILE_BUFFERS lpTrasmitBuffers, //文件傳輸之前和之後要發送的數據
DWORD dwFlags  //如下
);
typedef struct _TRANSMIT_FILE_BUFFERS{
PVOID Head; //文件發送之前要發送的數據
DWORD HeadLength;
PVOID Tail; //文件發送完成之後要發送的數據
DWORD TailLength;
}TRANSMIT_FILE_BUFFERS;
T F _ D I S C O N N E C T 數據發送完畢之後,開始執行套接字關閉
TF_REUSE_SOCKET允許套接字句柄再次做爲客戶機套接字用於AcceptEx中
T F _ U S E _ D E FA U LT _ W O R K E R 表明傳輸應該在系統默認線程場景中進。特別有利於長文件傳輸
T F _ U S E _ S Y S T E M _ T H R E A D 表明傳輸應該在系統線程場景中進行。同樣有利於長文件傳輸
T F _ U S E _ K E R N E L _ A P C 表明“內核異步進程調用”(A P C)應該對文件傳輸進行處理。如果把指定文件讀入緩衝區只需要一次讀取,該標誌便可提供一個重要的性能提升
T F _ W R I T E _ B E H I N D 表明Tr a n s m i t F i l e應該在無須遠程系統對所有的數據進行收到確認的情況下結束
 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章