winsock基础
1、Winsock初始化
int WSAStartup(WORD wVersionRequested ,LPWSADATA lpWSAData);
函數(shù)WSAStartup用于加載WinSock庫,
參數(shù) wVersionRequested 用于指定要加載的庫的版本,高字節(jié)表示副版本號(hào),低字節(jié)表示主版本號(hào);可使用宏MAKEWORD(x,y)設(shè)置獲得,其中x表示高字節(jié),y表示低字節(jié)。
參數(shù)lpWSAData是指向WSAData結(jié)構(gòu)的指針,WSAStartup函數(shù)通過此參數(shù)將其加載的WinSock版本相關(guān)信息反饋給調(diào)用者,
struct WSAData
{
WORD wVersion; //表示打算使用的版本
WORD wHighVersion; //系統(tǒng)現(xiàn)在最高支持的版本
char szDescription[WSADESCRIPTION_LEN+1]; //由特定的WinSock實(shí)施方案設(shè)定,基本沒用
char szSystemStatus[WSASYS_STATUS_LEN+1]; //同上
unsigned short iMaxSockets; //假設(shè)同時(shí)最多打開多少套接字,不用使用,因?yàn)橥瑫r(shí)最多打開的套接字?jǐn)?shù)目不是固定的,很大程度上跟物理內(nèi)存的多少有關(guān)
unsigned short iMaxUdpDg; //數(shù)據(jù)包的最大長度,不用使用,數(shù)據(jù)報(bào)的最大長度應(yīng)該使用WSAEnumProtocols獲得,
char FAR *lpVendorInfo; //為廠商預(yù)留的字段,
} WSADATA,FAR *LPWSADATA;
?
TCP編程
服務(wù)器端
1.建立socket套接字
2.bind將套接字綁定到指定的地址
int bind(SOCKET s,const struct sockaddr FAR* name,int namelen);//s等待客戶端連接的socket,name一個(gè)sockaddr緩沖區(qū)包含要使用的協(xié)議和地址相關(guān)信息,namelen緩沖區(qū)長度。
列:
SOCKET S;
struct sockaddr_in tcpaddr;
int port = 5150;
s = SOCKET(AF_INET,SOCK_STREAM,IPPROTO_TCP);
tcpaddr.sin_family = AF_INET;
tcpaddr.sin_port = htons(port);
tcpaddr.sin_addr.s_addr = htonl(INADDR_ANY);
bind(s,(SOCKADDR *)&tcpaddr,sizeof(tcpaddr));
3.listen設(shè)置為偵聽模式
int listen(SOCKET s,int backlog);//s要限定的套接字,backlog指定正在等待的最大連接數(shù)
4.accept,WSAAccept偵聽端口,接受連接
SOCKET accept(
SOCKET s,
struct sockaddr FAR *addr,
int FAR *addrlen
);
SOCKET WSAAccept(
SOCKET s,
struct sockaddr FAR *addr,
LPINT addrlen,
LPCONDITIONPROC lpfnCondition,
DWORD dwCallbackData);
WSAAccept頭三個(gè)參數(shù)與accept相同,lpfnCondition參數(shù)是指向函數(shù)的一個(gè)指針,函數(shù)根據(jù)客戶請(qǐng)求來調(diào)用,函數(shù)決定是否接受用戶的連接請(qǐng)求
定義如下:
int CALLBACK ConditionFunc(
LPWSABUF lpCallerID,
LPWSABUF lpCallerData,
LPQOS lpSQOS,
LPQOS lpGQOS,
LPWSABUFF lpCalleeID,
LPWSABUFF lpCalleeData,
GROUP FAR *g,
DWORD dwCallbackData
)
客戶端
1.創(chuàng)建SOCKET
2.解析服務(wù)器名
3.用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);
?
數(shù)據(jù)傳輸
1.發(fā)送數(shù)據(jù):send和WSASend
int send(SOCKET s,const char FAR *buf,int len,int flags);
2.接受數(shù)據(jù):recv和WSARecv
int? recv(SOCKET s,char FAR *buf,int len,int flags);
流協(xié)議
大多數(shù)面向連接的協(xié)議也是流協(xié)議,對(duì)于流協(xié)議套接字上收發(fā)數(shù)據(jù)不能保證對(duì)請(qǐng)求的數(shù)據(jù)量進(jìn)行讀或?qū)?#xff0c;
如:char sendbuff[2048];
int nBytes = 2048;
ret = send(s,sendbuff,nBytes,0);
對(duì)send函數(shù)而言,可能發(fā)出的少于2048個(gè)字節(jié),對(duì)于沒個(gè)收發(fā)數(shù)據(jù)的套接字來說,系統(tǒng)都為他們分配了相當(dāng)充足的的緩沖區(qū)空間,在發(fā)送數(shù)據(jù)時(shí),內(nèi)部緩沖區(qū)一直保留到應(yīng)該發(fā)到線上為止。幾種情況可導(dǎo)致這一情形發(fā)生:大量數(shù)據(jù)將緩沖區(qū)快速填滿,同時(shí)對(duì)TCP來說還有一個(gè)窗口大小的問題,接受端會(huì)對(duì)窗口大小進(jìn)行調(diào)整,以指出他可以接受多少數(shù)據(jù),這會(huì)使他在接受到一個(gè)新的大于0的窗口大小之前,不得在發(fā)送數(shù)據(jù)。必須將所以緩沖去的數(shù)據(jù)全都發(fā)送出去,可使用如下方式
char sendbuff[2048];
int nBytes = 2048;
int nLeft;
int idx;
nLeft = nByes;
idx = 0;
while(nLeft > 0)
{
ret = send(s,&sendbuff[idx],nLeft,0);
if (ret == SOCKET_ERROR)
{
//errr;
}
nLeft -= ret;
idx += ret;
}
中斷連接
1、從容關(guān)閉連接 shutdown
int shutdown(SOCKET s,int how);
2、closesocket
int closesocket(SOCKET s);
無連接協(xié)議(UDP):
1、接受端
int recvfrom(SOCKET s, char FAR *buf,int len, int flags,struct sockaddr FAR *from,int FAR *fromlen);
2、發(fā)送端
int sendto(SOCKET s,const char FAR *buf,int len,int flags,const struct sockaddr FAR *to,int FAR *tolen);
基于消息的協(xié)議
無連接協(xié)議大多都是基于消息的,對(duì)于面向連接的協(xié)議,協(xié)議本身提供了排序和邊界保護(hù)功能,而對(duì)于基于消息的對(duì)于寫入數(shù)據(jù)而言只能把它當(dāng)作他的自治行為。對(duì)于接受端來說,必須提供充足的緩沖區(qū),要不然,緩沖區(qū)不夠數(shù)據(jù)就會(huì)截?cái)鄟G失,被截?cái)嗟臄?shù)據(jù)無法恢復(fù),唯一的例外就是支持部分消息的協(xié)議
轉(zhuǎn)載于:https://www.cnblogs.com/liyunjin/archive/2010/08/29/1811785.html
總結(jié)
- 上一篇: (转)MVC模式参数传递的探究
- 下一篇: [Drupal] Submit and