Windwos 网络编程 第一章

来源:互联网 发布:js限制只能输入数字 编辑:程序博客网 时间:2024/06/06 03:11


Winsock 简介

         Winsock市一中标准API,主要用于网络中的数据通信,它允许两个或者多个应用程序进行网络相互通信。【Winsock是一种网络编程及诶偶,而不是协议】

1.1  Winsock头文件以及库文件

Winsock有两个版本,不过现在主要用到的是Winsock2

 

1.2  Winsock初始化

Windwos 网络编程   第一章

Winsock 简介

         Winsock市一中标准API,主要用于网络中的数据通信,它允许两个或者多个应用程序进行网络相互通信。【Winsock是一种网络编程及诶偶,而不是协议】

1.1  Winsock头文件以及库文件

Winsock有两个版本,不过现在主要用到的是Winsock2

 

1.2  Winsock初始化

int WSAStartup{

         WORDwVersionRequested,

         LPWSADATAlpWSAData

}

         在使用Winsock接口编写好应用程序之后,应该调用WSACleanup函数,这个函数能够使Winsock释放所有的Winsock分配的支援,取消应用程序挂起的Winsock调用。

         IntWSACleanup(void);

1.3  错误检查和处理

可以用WSAGetLastError汗水用户来获取错误。

1.4  协议寻址

1 IPv4 寻址

在IPv4中,计算机都分配一个地址,用一个32位的数值来表示。客户机通过TCP或者UDP和服务器通信时,必须制定服务器的IP地址和服务器端口。服务器打算监听传入的客户机请求时,必须制定一个ip地址和端口号。

SOCKADDR_IN 接口制定IP地址和服务端口信息

Struct sockaddr_in{

          Short        sin_family;               //必需设为AF_INET

U_short   sin_port;                   //TCP或UDP端口有次设置

Struct in_addr          sin_addr; //IPv4地址作为一个4字节的量存储

Char                  sin_zero[8]               //填充数

}

Inet_addr {

          Const char FAR *cp         //空终止字符串,用于接受点表示法的IP地址

};

字节排序

Big-endian排序,无意义到最有意义

Little-endian排序,有意义到无意义

把主机字节排序缓存网络字节排序

U_long hotol(u_longhcstlong);

Int WSAHtonl{

         Sockets,

U_long hostlong,

U_long Far* lplong

};

         U_shorthtons(u_short hostshort);

        

 

Int WSAHtons{

         Socket s, 

U_short nostshort,

         U_short FAR* lpshort;

};

Htonl 和WSAHtonl的hostlong参数是按主机字节顺序排序的一个4字节数。

下面4个函数是前面四个函数的逆向函数,把网络字节排序换成主机字数排序

U_long ntohl{…};

Int WSANtohl{…};

U_short ntohs(…)

Int WSANtohs{….}

1.5  创建套接字

SOCKET socket{

         Intaf,                //协议得之簇 AF_INET

          Int type,           //TCP设为SOCK_STREAD,UDP设为SOCK_DGRAM

         Intprotocol     //TCP设置为IPPROTO_TCPUDP设置为IPPROTO_UDP

}

1.6  面向连接通信

通过TCP/IP协议完成,TCP提供两个计算机之间可靠无误的数据传输。

1.6.1服务器API函数

                  服务器和客户端的基本调用

Socket()/WSASocekt()--->绑定--->监听---》Accept()/WSAAccept()

Socket()/WSASocket()--à地址解释---》connect()/WSAConnect()

1.6.1.1.1        绑定

Int bind{

         SOCKET           s,

         Const struct sockaddr FAR*  name,

Int    namelen        

};

1.6.1.2  监听

Int l    isten{

           SOCKET   a,     //被绑定的套接字

           Int backlog      //被搁置的链接的最大队列长度

};

1.6.1.3  接受连接

SOCKET accept{

           SOCKET s,

           Strcut sockaddrFAR* addr,

           Int FAR*   addrlen

};

1.6.2       客户端API

1 创建套接字

2      建立一个SOCKADDR地址结构,结构名称为准备连接到的服务器名。

3       用connect 或WSAConnection初始化客户机与服务器连接。

Connect函数

Int connect{

          SOCKET s,

          Const structsockaddr FAR*name,

          Int namelen

TCP/IP

Server

#include <stdio.h>

#include <WinSock2.h>

#pragma comment(lib, "ws2_32.lib")

 

int main(void)

{

         WSADATA wsaData;

         charbuffer[256]="hello client";

         SOCKET ListenSocket;

         SOCKET NewConnection;

         SOCKADDR_IN ServerAddr;

         intPort = 5150;

         intlen;

 

                  //初始化Winsock版本2.2

         WSAStartup(MAKEWORD(2, 2),&wsaData);

                 

                  //创建一个新的套接字来监听客户机连接

         ListenSocket = socket(AF_INET,SOCK_STREAM, IPPROTO_TCP);

 

                  //建立一个SOCKADDR_IN结构

         ServerAddr.sin_family       = AF_INET;

         ServerAddr.sin_port = htons(Port);

         ServerAddr.sin_addr.s_addr =htonl(INADDR_ANY);

         if(bind(ListenSocket,(SOCKADDR *) &ServerAddr,sizeof(ServerAddr)))

         {

                  printf("绑定地址失败");

                  return0;

         }

                  //监听客户连接,设置最大为5

         listen(ListenSocket, 5);

                  //连接到达时候接受一个新连接

         len = sizeof(ServerAddr);

         NewConnection = accept(ListenSocket,(SOCKADDR *)&ServerAddr, &len);

 

         //向客户端发送消息

         send(NewConnection,buffer,strlen(buffer),0);

         //接受消息

         memset(buffer,0,strlen(buffer));

         recv(NewConnection,buffer,256,0);

         printf(buffer);

         //关闭连接

         closesocket(NewConnection);

         closesocket(ListenSocket);

 

         //调用结束后

         WSACleanup();

         system("pause");

         return0;

}

 

Client:

#include <stdio.h>

#include <WinSock2.h>

#pragma  comment(lib,"ws2_32.lib")

 

int main(void)

{

         WSADATA wsaData;

         SOCKET  ClientSocket;

         SOCKADDR_IN ServerAddr;

         charbuffer[256] ="hello server";

         int             Port = 5150;

                 

                  //初始化Winsock2.2版本

         WSAStartup(MAKELANGID(2, 2),&wsaData);

                  //创建一个新的套接字建立客户连接

         ClientSocket = socket(AF_INET,SOCK_STREAM, IPPROTO_TCP);

 

                  //建立i一个SOCKADDR_IN结构

         ServerAddr.sin_family = AF_INET;

         ServerAddr.sin_port = htons(Port);

         ServerAddr.sin_addr.s_addr = inet_addr("127.0.0.1");

        

                  //建立套接字连接到一个服务器

         connect(ClientSocket, (SOCKADDR*)&ServerAddr, sizeof(ServerAddr));

 

                  //发送和处理数据

         send(ClientSocket,buffer,strlen(buffer),0);

         recv(ClientSocket,buffer,256,0);

         printf(buffer);

 

         closesocket(ClientSocket);

                  //应用程序完成连续的处理后调用WSACleanup

         WSACleanup();

         system("pause");

         return0;

}

1.6.3 数据传输

         收发数据是网络编程的主题,发送数据API函数send和WSASend 接收函数recv和WSARecv

         所有收发函数返回的错误代码都是SOCKET_ERROR。最常见的错误是WSAECONNABORTED和WSAECONNRESET,WSAEWOULDBLOCK。最后一个错误是套接字处于废阻塞模式或异步状态。

16.3.1 send和WSASend

         Int send{

                  SOCKET          s,                        //连接的套接字

                  Const char FAR* buf,                 //发送的数据

                  int len,                                 //缓存区字节数

                  int flags             //一般设置为0

};

出现的错误WSAECONNABORTED 虚拟回路由于超市或者协议有错而终端发生。

Int WSASend{

         SOCKET s,                //建立回话的有效句柄

         LPWSABUF  lpBuffers,           //独立的结构或者结构数组

         DWORD  dwBufferCount,                 //结构数量

         LPDWORD      lpNumberOfBytesSent,      //长度

         DWORD  dwFlags,            //在send函数中的有效参数

         LPWSAOVERLAPPED lpOverlapped,

                  LPWSAOVERLAPPED_COMPLETION_ROUTINlpCompletionRoutins

1.6.3.2 WSASendDisconnect

         Int WSASendDisconnect{

         SOCKET s,

         LPWSABUF    lpOutboundDisconnectData

} 一般不用

1.6.3.3

Int   recv{

                  SOCKET s,                //接受数据的套接字

                  Char  FAR* buf,               //缓冲

                  Int len,                        //长度

                  Int flags             //一般设置为0

]; 在基于消息或基于数据包的套接字上使用recv时,有几点应该注意,当挂起数据大于所体统的缓冲区时,缓冲区精良的当数据填满,recv条用会产生WSAEMSGSIZE错误,消息大小的错误是在使用面向消息协议发生的,面流协议TCP则把传入的数据缓存下来,并且尽量的返回引用程序所要求的数据,即使被挂起的数据比缓冲大。所以不错有这种错误。

Int  WSARecv{

         SOCKET s,                //建立回话的有效句柄

         LPWSABUF  lpBuffers,           //独立的结构或者结构数组

         DWORD  dwBufferCount,                 //结构数量

         LPDWORD      lpNumberOfBytesSent,      //长度

         DWORD  dwFlags,            //MSG_PEEK,MEG_OOB,MSG_PARTIAL

         LPWSAOVERLAPPED lpOverlapped,

                  LPWSAOVERLAPPED_COMPLETION_ROUTINlpCompletionRoutins

1.6.3.4  WSARecvDisconnect

Int  WSARecvDisconnect{

         SOCKET  s,

LPWSABUFA          LPiNBOUNDdISCONNECData

};

1.6.4  流协议

发送段

Char sendbuffer[2048];

Int nBytes = 2048;

Ret = send(s,sendbuff, nBytes, 0);

         对于send函数而已,可能会返回已发出的少于2048字节。因为对每个收发数据的套接字来说,系统都为他们分配了相当重铸的喊充裕,所以ret变量将谁为已发送的字节数,在发送数据时候,内部缓冲区会将数据一直保留到可以将它发到线上位置,集中创建的情况都可导致这一锌矿的发生。传输大量的数据可以把缓冲区数据填满,对于TCP/IP来说,还有窗口大小问题,接受段会对穿孔大小进行调节,只是它可以接受多少数据。如果大量数据,接收端就将窗口变为0,为挂起的数据做准备。对发送端来说,这样会强制在收到一个新的大于0的端口大小钱,不再发送数据,使用send汗冲去智能容纳1024字节,这时候有比较将剩下的也发送出去。

Char sendbuff[2048];

Internetnbytes =2048;

Int nLeft, idex;

 

nLeft = nBytes;

idx = 0;

while(nLeft>0)

{

         Ret = send(s, &sendbuff[idx],nLefn,0);

         If(ret == SOCKET_ERROR)

{//错误}

nLeft = ret;

idx += ret;

}

接收段

Char  recvbuffer[1024];

Int ret, nLeft, idx;

nLeft = 521;

idx = 0;

while(nLeft>0)

{

         Ret = recv(s,&recvbuff[idx], 0);

         If(ret == SOCKET_ERROR)

{//出错}

         Idx + = ret;

         nLeft -= ret;

}

1.6.5.1 shutdown

         为了保证通信放能够手段哦应用程序发出的所有数据,对于好的应用来说,应该通知接收端不再发送数据。同样通信对方也应该如此。这就是所谓的正常关闭的方法。

Int shutdown{

         SOCKET s,

         Int   how           //SD_RECEIVE, SD_SEND 或SD_BOTH

1.6.5.2 CLOSESOCKET

Int closesocket(SOCKET s);

1.7 无连接通信

1.7.1 接收端

         Int recvfrom{

                  SOCKET s,                //建立套接字

                  Char FAR*  buf,               //缓存区

                  Int len,               //长度

                  Int  flags,                  .//标志

                  Struct sockaddr  FAR* from,

                  Int FAR* fromlen

};

1.7.2 发送段

Int sendto{

         SOCET s,

         Const char FAR* buf,

         Int len,

         Int flags,

         Const struct sockaddr FAR* to,

         Int   tolen

};

 

Server.pp

int main(void)

{

         WSADATA wsaData;

         intPort = 5150;

         SOCKET    ReceveSocket;

         char           buffer[1024];

         SOCKADDR_IN      SendAddr;

         int           senderAddrSize =sizeof(SendAddr);

         memset(buffer, 0, 1024);

 

                  //初始化Winsock2.2

         WSAStartup(MAKELANGID(2, 2),&wsaData);

 

                  //创建一个新的套接字

         ReceveSocket = socket(AF_INET,SOCK_DGRAM, IPPROTO_UDP);

                  //有接口的数据包

         SendAddr.sin_family = AF_INET;

         SendAddr.sin_port = htons(Port);

         SendAddr.sin_addr.s_addr =htonl(INADDR_ANY);

                  //绑定地址

         if(bind(ReceveSocket, (SOCKADDR *)&SendAddr,sizeof(SendAddr)))

         {

                  printf("init error");

                  return0;

         }

                  //接受数据

         while(TRUE)

         {

                  recvfrom(ReceveSocket,buffer,1024,0,(SOCKADDR*)&SendAddr, &senderAddrSize);

                  printf(buffer);

         }

 

         closesocket(ReceveSocket);

         WSACleanup();

 

         system("pause");

         return0;

}

 

Client.cpp

int main(void)

{

 

         WSADATA wsaData;

         intPort = 5150;

         SOCKET    ReceveSocket;

         char           buffer[1024] ="hello";

         SOCKADDR_IN      SendAddr;

         int           senderAddrSize =sizeof(SendAddr);

 

         //初始化Winsock2.2

         WSAStartup(MAKELANGID(2, 2),&wsaData);

 

         //创建一个新的套接字

         ReceveSocket = socket(AF_INET,SOCK_DGRAM, IPPROTO_UDP);

         //有接口的数据包

         SendAddr.sin_family = AF_INET;

         SendAddr.sin_port = htons(Port);

         SendAddr.sin_addr.s_addr = inet_addr("127.0.0.1");

 

                  //发送消息

         sendto(ReceveSocket,buffer,1024,0,(SOCKADDR*)&SendAddr, senderAddrSize);

 

         closesocket(ReceveSocket);

 

         WSACleanup();

         system("pause");

         return0;

}

1.8 其他API函数

1.8.1 getpeername获取通信方的套接字地址信息

         SOCKET   s,

         struct   sockaddr FAR* name,

         intFAR*  namelen

1.8.2 getsockname     获取网络地址

         Int  getsockname{

                  SOCKET s,

                  Struct       sockaddr   FAR*  name,

                  Int  FAR* name;

};

1.8.3WSADuplicateSocket

         建立WSAPROTOCOL-INFO结构,该结构可传递到其他进程。

         Int WSADuplicateSocket{

                  SOCKET     s,

                  DWORD           dwProcessId,

                  LPWSAPROTOCOL_INFO      lpProtocolInfo

}

int WSAStartup{

         WORDwVersionRequested,

         LPWSADATAlpWSAData

}

         在使用Winsock接口编写好应用程序之后,应该调用WSACleanup函数,这个函数能够使Winsock释放所有的Winsock分配的支援,取消应用程序挂起的Winsock调用。

         IntWSACleanup(void);

1.3  错误检查和处理

可以用WSAGetLastError汗水用户来获取错误。

1.4  协议寻址

1 IPv4 寻址

在IPv4中,计算机都分配一个地址,用一个32位的数值来表示。客户机通过TCP或者UDP和服务器通信时,必须制定服务器的IP地址和服务器端口。服务器打算监听传入的客户机请求时,必须制定一个ip地址和端口号。

SOCKADDR_IN 接口制定IP地址和服务端口信息

Struct sockaddr_in{

          Short        sin_family;               //必需设为AF_INET

U_short   sin_port;                   //TCP或UDP端口有次设置

Struct in_addr          sin_addr; //IPv4地址作为一个4字节的量存储

Char                  sin_zero[8]               //填充数

}

Inet_addr {

          Const char FAR *cp         //空终止字符串,用于接受点表示法的IP地址

};

字节排序

Big-endian排序,无意义到最有意义

Little-endian排序,有意义到无意义

把主机字节排序缓存网络字节排序

U_long hotol(u_longhcstlong);

Int WSAHtonl{

         Sockets,

U_long hostlong,

U_long Far* lplong

};

         U_shorthtons(u_short hostshort);

        

 

Int WSAHtons{

         Socket s, 

U_short nostshort,

         U_short FAR* lpshort;

};

Htonl 和WSAHtonl的hostlong参数是按主机字节顺序排序的一个4字节数。

下面4个函数是前面四个函数的逆向函数,把网络字节排序换成主机字数排序

U_long ntohl{…};

Int WSANtohl{…};

U_short ntohs(…)

Int WSANtohs{….}

1.5  创建套接字

SOCKET socket{

         Intaf,                //协议得之簇 AF_INET

          Int type,           //TCP设为SOCK_STREAD,UDP设为SOCK_DGRAM

         Intprotocol     //TCP设置为IPPROTO_TCPUDP设置为IPPROTO_UDP

}

1.6  面向连接通信

通过TCP/IP协议完成,TCP提供两个计算机之间可靠无误的数据传输。

1.6.1服务器API函数

                  服务器和客户端的基本调用

Socket()/WSASocekt()--->绑定--->监听---》Accept()/WSAAccept()

Socket()/WSASocket()--à地址解释---》connect()/WSAConnect()

1.6.1.1.1        绑定

Int bind{

         SOCKET           s,

         Const struct sockaddr FAR*  name,

Int    namelen        

};

1.6.1.2  监听

Int l    isten{

           SOCKET   a,     //被绑定的套接字

           Int backlog      //被搁置的链接的最大队列长度

};

1.6.1.3  接受连接

SOCKET accept{

           SOCKET s,

           Strcut sockaddrFAR* addr,

           Int FAR*   addrlen

};

1.6.2       客户端API

1 创建套接字

2      建立一个SOCKADDR地址结构,结构名称为准备连接到的服务器名。

3       用connect 或WSAConnection初始化客户机与服务器连接。

Connect函数

Int connect{

          SOCKET s,

          Const structsockaddr FAR*name,

          Int namelen

TCP/IP

Server

#include <stdio.h>

#include <WinSock2.h>

#pragma comment(lib, "ws2_32.lib")

 

int main(void)

{

         WSADATA wsaData;

         charbuffer[256]="hello client";

         SOCKET ListenSocket;

         SOCKET NewConnection;

         SOCKADDR_IN ServerAddr;

         intPort = 5150;

         intlen;

 

                  //初始化Winsock版本2.2

         WSAStartup(MAKEWORD(2, 2),&wsaData);

                 

                  //创建一个新的套接字来监听客户机连接

         ListenSocket = socket(AF_INET,SOCK_STREAM, IPPROTO_TCP);

 

                  //建立一个SOCKADDR_IN结构

         ServerAddr.sin_family       = AF_INET;

         ServerAddr.sin_port = htons(Port);

         ServerAddr.sin_addr.s_addr =htonl(INADDR_ANY);

         if(bind(ListenSocket,(SOCKADDR *) &ServerAddr,sizeof(ServerAddr)))

         {

                  printf("绑定地址失败");

                  return0;

         }

                  //监听客户连接,设置最大为5

         listen(ListenSocket, 5);

                  //连接到达时候接受一个新连接

         len = sizeof(ServerAddr);

         NewConnection = accept(ListenSocket,(SOCKADDR *)&ServerAddr, &len);

 

         //向客户端发送消息

         send(NewConnection,buffer,strlen(buffer),0);

         //接受消息

         memset(buffer,0,strlen(buffer));

         recv(NewConnection,buffer,256,0);

         printf(buffer);

         //关闭连接

         closesocket(NewConnection);

         closesocket(ListenSocket);

 

         //调用结束后

         WSACleanup();

         system("pause");

         return0;

}

 

Client:

#include <stdio.h>

#include <WinSock2.h>

#pragma  comment(lib,"ws2_32.lib")

 

int main(void)

{

         WSADATA wsaData;

         SOCKET  ClientSocket;

         SOCKADDR_IN ServerAddr;

         charbuffer[256] ="hello server";

         int             Port = 5150;

                 

                  //初始化Winsock2.2版本

         WSAStartup(MAKELANGID(2, 2),&wsaData);

                  //创建一个新的套接字建立客户连接

         ClientSocket = socket(AF_INET,SOCK_STREAM, IPPROTO_TCP);

 

                  //建立i一个SOCKADDR_IN结构

         ServerAddr.sin_family = AF_INET;

         ServerAddr.sin_port = htons(Port);

         ServerAddr.sin_addr.s_addr = inet_addr("127.0.0.1");

        

                  //建立套接字连接到一个服务器

         connect(ClientSocket, (SOCKADDR*)&ServerAddr, sizeof(ServerAddr));

 

                  //发送和处理数据

         send(ClientSocket,buffer,strlen(buffer),0);

         recv(ClientSocket,buffer,256,0);

         printf(buffer);

 

         closesocket(ClientSocket);

                  //应用程序完成连续的处理后调用WSACleanup

         WSACleanup();

         system("pause");

         return0;

}

1.6.3 数据传输

         收发数据是网络编程的主题,发送数据API函数send和WSASend 接收函数recv和WSARecv

         所有收发函数返回的错误代码都是SOCKET_ERROR。最常见的错误是WSAECONNABORTED和WSAECONNRESET,WSAEWOULDBLOCK。最后一个错误是套接字处于废阻塞模式或异步状态。

16.3.1 send和WSASend

         Int send{

                  SOCKET          s,                        //连接的套接字

                  Const char FAR* buf,                 //发送的数据

                  int len,                                 //缓存区字节数

                  int flags             //一般设置为0

};

出现的错误WSAECONNABORTED 虚拟回路由于超市或者协议有错而终端发生。

Int WSASend{

         SOCKET s,                //建立回话的有效句柄

         LPWSABUF  lpBuffers,           //独立的结构或者结构数组

         DWORD  dwBufferCount,                 //结构数量

         LPDWORD      lpNumberOfBytesSent,      //长度

         DWORD  dwFlags,            //在send函数中的有效参数

         LPWSAOVERLAPPED lpOverlapped,

                  LPWSAOVERLAPPED_COMPLETION_ROUTINlpCompletionRoutins

1.6.3.2 WSASendDisconnect

         Int WSASendDisconnect{

         SOCKET s,

         LPWSABUF    lpOutboundDisconnectData

} 一般不用

1.6.3.3

Int   recv{

                  SOCKET s,                //接受数据的套接字

                  Char  FAR* buf,               //缓冲

                  Int len,                        //长度

                  Int flags             //一般设置为0

]; 在基于消息或基于数据包的套接字上使用recv时,有几点应该注意,当挂起数据大于所体统的缓冲区时,缓冲区精良的当数据填满,recv条用会产生WSAEMSGSIZE错误,消息大小的错误是在使用面向消息协议发生的,面流协议TCP则把传入的数据缓存下来,并且尽量的返回引用程序所要求的数据,即使被挂起的数据比缓冲大。所以不错有这种错误。

Int  WSARecv{

         SOCKET s,                //建立回话的有效句柄

         LPWSABUF  lpBuffers,           //独立的结构或者结构数组

         DWORD  dwBufferCount,                 //结构数量

         LPDWORD      lpNumberOfBytesSent,      //长度

         DWORD  dwFlags,            //MSG_PEEK,MEG_OOB,MSG_PARTIAL

         LPWSAOVERLAPPED lpOverlapped,

                  LPWSAOVERLAPPED_COMPLETION_ROUTINlpCompletionRoutins

1.6.3.4  WSARecvDisconnect

Int  WSARecvDisconnect{

         SOCKET  s,

LPWSABUFA          LPiNBOUNDdISCONNECData

};

1.6.4  流协议

发送段

Char sendbuffer[2048];

Int nBytes = 2048;

Ret = send(s,sendbuff, nBytes, 0);

         对于send函数而已,可能会返回已发出的少于2048字节。因为对每个收发数据的套接字来说,系统都为他们分配了相当重铸的喊充裕,所以ret变量将谁为已发送的字节数,在发送数据时候,内部缓冲区会将数据一直保留到可以将它发到线上位置,集中创建的情况都可导致这一锌矿的发生。传输大量的数据可以把缓冲区数据填满,对于TCP/IP来说,还有窗口大小问题,接受段会对穿孔大小进行调节,只是它可以接受多少数据。如果大量数据,接收端就将窗口变为0,为挂起的数据做准备。对发送端来说,这样会强制在收到一个新的大于0的端口大小钱,不再发送数据,使用send汗冲去智能容纳1024字节,这时候有比较将剩下的也发送出去。

Char sendbuff[2048];

Internetnbytes =2048;

Int nLeft, idex;

 

nLeft = nBytes;

idx = 0;

while(nLeft>0)

{

         Ret = send(s, &sendbuff[idx],nLefn,0);

         If(ret == SOCKET_ERROR)

{//错误}

nLeft = ret;

idx += ret;

}

接收段

Char  recvbuffer[1024];

Int ret, nLeft, idx;

nLeft = 521;

idx = 0;

while(nLeft>0)

{

         Ret = recv(s,&recvbuff[idx], 0);

         If(ret == SOCKET_ERROR)

{//出错}

         Idx + = ret;

         nLeft -= ret;

}

1.6.5.1 shutdown

         为了保证通信放能够手段哦应用程序发出的所有数据,对于好的应用来说,应该通知接收端不再发送数据。同样通信对方也应该如此。这就是所谓的正常关闭的方法。

Int shutdown{

         SOCKET s,

         Int   how           //SD_RECEIVE, SD_SEND 或SD_BOTH

1.6.5.2 CLOSESOCKET

Int closesocket(SOCKET s);

1.7 无连接通信

1.7.1 接收端

         Int recvfrom{

                  SOCKET s,                //建立套接字

                  Char FAR*  buf,               //缓存区

                  Int len,               //长度

                  Int  flags,                  .//标志

                  Struct sockaddr  FAR* from,

                  Int FAR* fromlen

};

1.7.2 发送段

Int sendto{

         SOCET s,

         Const char FAR* buf,

         Int len,

         Int flags,

         Const struct sockaddr FAR* to,

         Int   tolen

};

 

Server.pp

int main(void)

{

         WSADATA wsaData;

         intPort = 5150;

         SOCKET    ReceveSocket;

         char           buffer[1024];

         SOCKADDR_IN      SendAddr;

         int           senderAddrSize =sizeof(SendAddr);

         memset(buffer, 0, 1024);

 

                  //初始化Winsock2.2

         WSAStartup(MAKELANGID(2, 2),&wsaData);

 

                  //创建一个新的套接字

         ReceveSocket = socket(AF_INET,SOCK_DGRAM, IPPROTO_UDP);

                  //有接口的数据包

         SendAddr.sin_family = AF_INET;

         SendAddr.sin_port = htons(Port);

         SendAddr.sin_addr.s_addr =htonl(INADDR_ANY);

                  //绑定地址

         if(bind(ReceveSocket, (SOCKADDR *)&SendAddr,sizeof(SendAddr)))

         {

                  printf("init error");

                  return0;

         }

                  //接受数据

         while(TRUE)

         {

                  recvfrom(ReceveSocket,buffer,1024,0,(SOCKADDR*)&SendAddr, &senderAddrSize);

                  printf(buffer);

         }

 

         closesocket(ReceveSocket);

         WSACleanup();

 

         system("pause");

         return0;

}

 

Client.cpp

int main(void)

{

 

         WSADATA wsaData;

         intPort = 5150;

         SOCKET    ReceveSocket;

         char           buffer[1024] ="hello";

         SOCKADDR_IN      SendAddr;

         int           senderAddrSize =sizeof(SendAddr);

 

         //初始化Winsock2.2

         WSAStartup(MAKELANGID(2, 2),&wsaData);

 

         //创建一个新的套接字

         ReceveSocket = socket(AF_INET,SOCK_DGRAM, IPPROTO_UDP);

         //有接口的数据包

         SendAddr.sin_family = AF_INET;

         SendAddr.sin_port = htons(Port);

         SendAddr.sin_addr.s_addr = inet_addr("127.0.0.1");

 

                  //发送消息

         sendto(ReceveSocket,buffer,1024,0,(SOCKADDR*)&SendAddr, senderAddrSize);

 

         closesocket(ReceveSocket);

 

         WSACleanup();

         system("pause");

         return0;

}

1.8 其他API函数

1.8.1 getpeername获取通信方的套接字地址信息

         SOCKET   s,

         struct   sockaddr FAR* name,

         intFAR*  namelen

1.8.2 getsockname     获取网络地址

         Int  getsockname{

                  SOCKET s,

                  Struct       sockaddr   FAR*  name,

                  Int  FAR* name;

};

1.8.3WSADuplicateSocket

         建立WSAPROTOCOL-INFO结构,该结构可传递到其他进程。

         Int WSADuplicateSocket{

                  SOCKET     s,

                  DWORD           dwProcessId,

                  LPWSAPROTOCOL_INFO      lpProtocolInfo

}

原创粉丝点击