在上一篇随笔中,对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...**\n";
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!**\n";
69 
70     cout<<"**We are going to close the client connection...**\n";
71 
72     closesocket(ReceivingSocket);
73     WSACleanup();
74 
75     return 0;
76 }
Receiver Code

 

 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>.\n";
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) << "...\n";
48 
49     cout << "We will now try to send a hello message.\n";
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).\n";
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.\n";
65 
66     closesocket(SendingSocket);
67 
68     // When your application is finished handling the connection, call
69     // WSACleanup.
70 
71     WSACleanup();
72     return 0;
73 }
Sender Code