UDP是一种不可靠的传输协议,使用UDP通讯的双方,服务器不需要监听、等待客户端连接,客户端也不需要连接服务器后再发送消息,双方使用recvfrom()函数和sendto()函数收发消息,这两个函数的原型如下:
int recvfrom( _In_ SOCKET s, _Out_ char *buf, _In_ int len, _In_ int flags, _Out_ struct sockaddr *from, _Inout_opt_ int *fromlen );
s [in]
A descriptoridentifying a bound socket.
buf [out]
A buffer for theincoming data.
len [in]
The length, in bytes,of the buffer pointed to by the buf parameter.
flags [in]
A set of options thatmodify the behavior of the function call beyond the options specified for theassociated socket. See the Remarks below for more details.
from [out]
An optional pointerto a buffer in a sockaddr structurethat will hold the source address upon return.
fromlen [in, out, optional]
An optional pointerto the size, in bytes, of the buffer pointed to by the from parameter.
int sendto( _In_ SOCKET s, _In_ const char *buf, _In_ int len, _In_ int flags, _In_ const struct sockaddr *to, _In_ int tolen );
s [in]
A descriptoridentifying a (possibly connected) socket.
buf [in]
A pointer to a buffercontaining the data to be transmitted.
len [in]
The length, in bytes,of the data pointed to by the buf parameter.
flags [in]
A set of flags thatspecify the way in which the call is made.
to [in]
An optional pointerto a sockaddr structurethat contains the address of the target socket.
tolen [in]
The size, in bytes,of the address pointed to by the to parameter.
下面通过一个例子来说明具体的通信过程。
// UDPServer.cpp : Defines the entry point for the console application. #pragma comment (lib,"ws2_32.lib") #include <Winsock2.h> #include <iostream> using namespace std; void main() { //版本协商 WORD wVersionRequested; WSADATA wsaData; int err; wVersionRequested = MAKEWORD( 1, 1 ); err = WSAStartup( wVersionRequested, &wsaData ); if ( err != 0 ) { /* Tell the user that we could not find a usable */ /* WinSock DLL. */ return; } /* Confirm that the WinSock DLL supports 2.2.*/ /* Note that if the DLL supports versions greater */ /* than 2.2 in addition to 2.2, it will still return */ /* 2.2 in wVersion since that is the version we */ /* requested. */ if ( LOBYTE( wsaData.wVersion ) != 1 || HIBYTE( wsaData.wVersion ) != 1) { /* Tell the user that we could not find a usable */ /* WinSock DLL. */ WSACleanup( ); return; } /* The WinSock DLL is acceptable. Proceed. */ //创建数据报套接字 SOCKET svr = socket(AF_INET,SOCK_DGRAM,0); //创建本地地址信息 SOCKADDR_IN addr; addr.sin_family = AF_INET; addr.sin_port = htons(6000); addr.sin_addr.S_un.S_addr = htonl(INADDR_ANY); int len = sizeof(sockaddr); bind(svr,(sockaddr*)&addr,len); //创建客户端地址对象 SOCKADDR_IN addrClient; char recvBuf[128]; char sendBuf[128]; char tempBuf[256]; while(true) { //接收数据 recvfrom(svr,recvBuf,128,0,(sockaddr*)&addrClient,&len); //将一个以网络字节顺序排列的IP地址转换为一个字符串IP地址 char* ipClient = inet_ntoa(addrClient.sin_addr); cout<<ipClient<<" said:"<<recvBuf<<endl; cin>>sendBuf; //发送数据 sendto(svr,sendBuf,strlen(sendBuf)+1,0,(sockaddr*)&addrClient,len); } closesocket(svr); WSACleanup(); }
// UDPClient.cpp : Defines the entry point for the console application. #pragma comment (lib,"ws2_32.lib") #include <Winsock2.h> #include <iostream> using namespace std; void main() { //版本协商 WORD wVersionRequested; WSADATA wsaData; int err; wVersionRequested = MAKEWORD( 1, 1 ); err = WSAStartup( wVersionRequested, &wsaData ); if ( err != 0 ) { /* Tell the user that we could not find a usable */ /* WinSock DLL. */ return; } /* Confirm that the WinSock DLL supports 2.2.*/ /* Note that if the DLL supports versions greater */ /* than 2.2 in addition to 2.2, it will still return */ /* 2.2 in wVersion since that is the version we */ /* requested. */ if ( LOBYTE( wsaData.wVersion ) != 1 || HIBYTE( wsaData.wVersion ) != 1 ) { /* Tell the user that we could not find a usable */ /* WinSock DLL. */ WSACleanup( ); return; } /* The WinSock DLL is acceptable. Proceed. */ //创建服务器套接字 SOCKET Svr = socket(AF_INET,SOCK_DGRAM,0); //创建地址 SOCKADDR_IN addrSvr; addrSvr.sin_family = AF_INET; addrSvr.sin_port = htons(6000); addrSvr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); char recvBuf[128]; char sendBuf[128]; int len = sizeof(sockaddr); while(true) { //gets_s(sendBuf); cin>>sendBuf; //发送数据 sendto(Svr,sendBuf,strlen(sendBuf)+1,0,(sockaddr*)&addrSvr,len); //接收数据 recvfrom(Svr,recvBuf,128,0,(sockaddr*)&addrSvr,&len); //将一个以网络字节顺序排列的IP地址转换为一个字符串IP地址 char* ipSvr = inet_ntoa(addrSvr.sin_addr); //printf("%s said: %s/n",ipSvr,recvBuf); cout<<ipSvr<<" said:"<<recvBuf<<endl; } closesocket(Svr); WSACleanup(); }
参考:
http://blog.csdn.net/nyzhl/article/details/2612848
http://msdn.microsoft.com/en-us/library/windows/desktop/ms740120(v=vs.85).aspx
http://msdn.microsoft.com/en-us/library/windows/d