在上一篇随笔中,对Winsock中基于tcp面向连接的Server和Client通信进行了说明,但是,Winsock中,Server和Client间还可以通过无连接通信,也就是采用UDP协议。。
因此,这一篇随笔也简单的列举基于UDP的Server和Client的实现。。
和基于TCP的实现相比,其主要的不同点包括:
①接收端(简单地说就是服务器)/发送端(简单地说就是客户端)在创建Socket时候,参数要选择SOCK_DGRAM, IPPROTO_UDP;
②接收端不需要调用listen和accept函数,而是通过recvfrom/WSArecvfrom函数接收数据报;
③发送端通过sendto/WSAsendto接收数据报;
接收端和发送端的代码如下:
1 #include"winsock2.h" 2 #include<iostream> 3 using namespace std; 4 //This line is very important 5 6 #pragma comment(lib,"ws2_32.lib") 7 int main() 8 { 9 WSADATA wsaData; 10 SOCKET ReceivingSocket; 11 SOCKADDR_IN ReceiverAddr; 12 int Port = 5150; 13 char ReceiveBuf[1024]; 14 int BufLength = 1024; 15 SOCKADDR_IN SenderAddr; 16 int SenderAddrSize = sizeof(SenderAddr); 17 int Ret; 18 19 if ((Ret = WSAStartup(MAKEWORD(2,2), &wsaData)) != 0) 20 { 21 cout<<"WSAStartup failed with error "<<Ret<<endl; 22 //here no WSACleanup,because we do not create anything; 23 return -1; 24 } 25 26 // Create a new socket to listening for client connections. 27 //Note the difference with TCP 28 ReceivingSocket = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP); 29 if ( INVALID_SOCKET == ReceivingSocket) 30 { 31 cout<<"Socket failed with error "<<WSAGetLastError()<<endl; 32 WSACleanup(); 33 return -1; 34 } 35 36 ReceiverAddr.sin_family = AF_INET; 37 ReceiverAddr.sin_addr.s_addr = htonl(INADDR_ANY); 38 ReceiverAddr.sin_port = htons(Port); 39 40 //to bind 41 if (bind(ReceivingSocket, (SOCKADDR *)&ReceiverAddr, sizeof(ReceiverAddr)) == SOCKET_ERROR) 42 { 43 cout<<"Binding failed with error "<<WSAGetLastError()<<endl; 44 closesocket(ReceivingSocket); 45 WSACleanup(); 46 return -1; 47 } 48 49 // Listen for client connections. We used a backlog of 5 which is 50 // normal for many applications. 51 52 cout<<"** We are ready to receive 1 datagram from any interface on port "<<Port<<"**"<<endl; 53 54 //accep a connection when one arrives 55 56 57 58 cout<<"** We are waiting for data...** "; 59 //SenderAddrSize = sizeof(SenderAddr); 60 Ret = recvfrom(ReceivingSocket,ReceiveBuf,BufLength,0,(SOCKADDR *)&SenderAddr,&SenderAddrSize); 61 if (SOCKET_ERROR == Ret) 62 { 63 cout<<"Recvfrom failed with error "<<WSAGetLastError()<<endl; 64 closesocket(ReceivingSocket); 65 WSACleanup(); 66 return -1; 67 } 68 cout<<"**We have successfully recieve "<<Ret<<" Byte(s) data!** "; 69 70 cout<<"**We are going to close the client connection...** "; 71 72 closesocket(ReceivingSocket); 73 WSACleanup(); 74 75 return 0; 76 }
1 #include"winsock2.h" 2 #include<iostream> 3 #include <time.h> 4 using namespace std; 5 //This line is very important 6 7 #pragma comment(lib,"ws2_32.lib") 8 int main(int argc, char **argv) 9 { 10 WSADATA wsaData; 11 SOCKET SendingSocket; 12 SOCKADDR_IN ReceiverAddr; 13 int Port = 5150; 14 int Ret; 15 16 if (argc <= 1) 17 { 18 cout<<"USAGE: udpclient <Server IP address>. "; 19 return -1; 20 } 21 22 // Initialize Winsock version 2.2 23 24 if ((Ret = WSAStartup(MAKEWORD(2,2), &wsaData)) != 0) 25 { 26 cout<<"WSAStartup failed with error "<<Ret<<endl; 27 return -1; 28 } 29 30 // Create a new socket to make a client connection. 31 32 SendingSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);//Note the difference with TCP 33 if (INVALID_SOCKET == SendingSocket) 34 { 35 cout << "socket failed with error " << WSAGetLastError()<<endl; 36 WSACleanup(); 37 return -1; 38 } 39 40 ReceiverAddr.sin_family = AF_INET; 41 ReceiverAddr.sin_port = htons(Port); 42 ReceiverAddr.sin_addr.s_addr = inet_addr(argv[1]); 43 44 // Make a connection to the server with socket s. 45 46 cout<< "We are trying to connect to " << inet_ntoa(ReceiverAddr.sin_addr) 47 << ":" << htons(ReceiverAddr.sin_port) << "... "; 48 49 cout << "We will now try to send a hello message. "; 50 51 if ((Ret = sendto(SendingSocket, "Hello", 5, 0, (SOCKADDR *)&ReceiverAddr,sizeof(ReceiverAddr))) == SOCKET_ERROR) 52 { 53 cout << "Sendto failed with error " << WSAGetLastError()<<endl; 54 closesocket(SendingSocket); 55 WSACleanup(); 56 return -1; 57 } 58 59 cout << "We successfully sent " << Ret << " byte(s). "; 60 61 // When you are finished sending and receiving data on socket s, 62 // you should close the socket. 63 64 cout << "We are closing the connection. "; 65 66 closesocket(SendingSocket); 67 68 // When your application is finished handling the connection, call 69 // WSACleanup. 70 71 WSACleanup(); 72 return 0; 73 }