无连接通信UDP
无连接通信是通过UDP/IP协议完成的。UDP不能确保可靠的数据传输,但能将数据发送到过个目标,或者接收多个源数据。
UDP通信不用调用listen和accept。接收函数有recvfrom,和WSARecvFrom。
int recvfrom( _In_ SOCKET s, _Out_ char *buf, _In_ int len, _In_ int flags,//一般填0,具体看MSDN _Out_ struct sockaddr *from,//返回接收端的地址信息 _Inout_opt_ int *fromlen //指向地址结构的长度 );
int WSARecvFrom( _In_ SOCKET s, _Inout_ LPWSABUF lpBuffers, _In_ DWORD dwBufferCount, _Out_ LPDWORD lpNumberOfBytesRecvd, _Inout_ LPDWORD lpFlags, _Out_ struct sockaddr *lpFrom, _Inout_ LPINT lpFromlen, _In_ LPWSAOVERLAPPED lpOverlapped, _In_ LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine );
- UDP接收端应用程序
#include<winsock2.h> #include<Ws2tcpip.h> #pragma comment(lib,"WS2_32") int main(void) { WSADATA wsaData; SOCKET receivingSocket; SOCKADDR_IN ReceiverAddr; int Port = 5150; char ReceiveBuf[1024]; int BufLength = 1024; SOCKADDR_IN SenderAddr; int SenderAddrSize = sizeof(SenderAddr); WSAStartup(MAKEWORD(2, 2), &wsaData); //创建一个新的套接字来接收数据报 receivingSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); //建立一个SOCKADDR_IN结构,这个结构将告知我们想要使用5150端口来接收来自所有接口的数据报 ReceiverAddr.sin_family = AF_INET; ReceiverAddr.sin_port = htons(Port); inet_pton(AF_INET, INADDR_ANY, (void*)&ReceiverAddr.sin_addr.S_un.S_addr); //使用bind将这个地址信息和套接字关联起来 bind(receivingSocket, (SOCKADDR*)&SenderAddr, sizeof(SenderAddr)); //此时可以在绑定套接字上接收数据报了 recvfrom(receivingSocket, ReceiveBuf, BufLength, 0, (SOCKADDR*)&SenderAddr, &SenderAddrSize); //应用程序接收完数据报后。关闭套接字 closesocket(receivingSocket); WSACleanup(); return 1; }
发送函数有sendto,和WSASendto。
int sendto( _In_ SOCKET s, //socket描述符 _In_ const char *buf, //数据报缓存地址 _In_ int len, //数据报长度 _In_ int flags, //该参数一般为0 _In_ const struct sockaddr *to, //数据发往哪里 _In_ int tolen //对方地址长度 );//返回发送的字节数
int WSASendTo( _In_ SOCKET s, _In_ LPWSABUF lpBuffers, _In_ DWORD dwBufferCount, _Out_ LPDWORD lpNumberOfBytesSent, _In_ DWORD dwFlags, _In_ const struct sockaddr *lpTo, _In_ int iToLen, _In_ LPWSAOVERLAPPED lpOverlapped, _In_ LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine );
- UDP发送端示例:
WSADATA wsaData; SOCKET SendingSocket; SOCKADDR_IN ReceiverAddr; int Port = 5150; char SendBuf[1024]; int BufLength = 1024; WSAStartup(MAKEWORD(2, 2), &wsaData); SendingSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); ReceiverAddr.sin_family = AF_INET; ReceiverAddr.sin_port = htons(Port); inet_pton(AF_INET, "136.149.3.29", (void*)&ReceiverAddr); sendto(SendingSocket, SendBuf, BufLength, 0, (SOCKADDR*)&ReceiverAddr, sizeof(ReceiverAddr)); closesocket(SendingSocket); WSACleanup();
常用winsock API。
- 获取通信方的套接字地址信息,该信息是关于已建立连接的套接字。
int getpeername( _In_ SOCKET s, //准备连接的套接字 _Out_ struct sockaddr *name, _Inout_ int *namelen );
- 获取给定套接字本地接口信息。
int getsockname( _In_ SOCKET s, _Out_ struct sockaddr *name, _Inout_ int *namelen );
声明:以上整理于Windows网络编程(第二版)