UDP sockets
UDP stands for User Datagram Protocol and is an alternative protocol to TCP the most common protocol used for data transfer over the internet.
UDP is different from TCP in a number of ways. Most importantly UDP is a connectionless protocol.
TCP vs UDP
In the TCP protocol first a connection is established by performing the 3 step handshake. This is done by calling the connect() socket function. However there is no such connection established in UDP.
In simple terms when using the udp protocol, the client throws a packet at the server and its upto the server whether it catches it or not. If it fails then the udp protocol is not concerned.
This is opposite to what happens in the TCP protocol. If the receiver side fails to receive a packet then the sender side will find it out and resend the packet till it is properly received by the receiver. This is precisely the concept of connection.
Coding UDP Sockets
In this article we are going to do some very simple udp socket programming by making a server and a client. We shall be doing this on the windows platform and on windows the socket api is called winsock.
For coding its recommended to use VC++ 6.0 or 2010 express edition which is free and can be downloaded from microsoft.com
UDP Server
The following program will launch a udp server that can accept incoming udp connections.
Here is the code for the server:
/* Simple UDP Server */ #include<stdio.h> #include<winsock2.h> #pragma comment(lib,"ws2_32.lib") //Winsock Library #define BUFLEN 512 //Max length of buffer #define PORT 8888 //The port on which to listen for incoming data int main() { SOCKET s; struct sockaddr_in server, si_other; int slen , recv_len; char buf[BUFLEN]; WSADATA wsa; slen = sizeof(si_other) ; //Initialise winsock printf("\nInitialising Winsock..."); if (WSAStartup(MAKEWORD(2,2),&wsa) != 0) { printf("Failed. Error Code : %d",WSAGetLastError()); exit(EXIT_FAILURE); } printf("Initialised.\n"); //Create a socket if((s = socket(AF_INET , SOCK_DGRAM , 0 )) == INVALID_SOCKET) { printf("Could not create socket : %d" , WSAGetLastError()); } printf("Socket created.\n"); //Prepare the sockaddr_in structure server.sin_family = AF_INET; server.sin_addr.s_addr = INADDR_ANY; server.sin_port = htons( PORT ); //Bind if( bind(s ,(struct sockaddr *)&server , sizeof(server)) == SOCKET_ERROR) { printf("Bind failed with error code : %d" , WSAGetLastError()); exit(EXIT_FAILURE); } puts("Bind done"); //keep listening for data while(1) { printf("Waiting for data..."); fflush(stdout); //clear the buffer by filling null, it might have previously received data memset(buf,'/* Simple UDP Server */ #include<stdio.h> #include<winsock2.h> #pragma comment(lib,"ws2_32.lib") //Winsock Library #define BUFLEN 512 //Max length of buffer #define PORT 8888 //The port on which to listen for incoming data int main() { SOCKET s; struct sockaddr_in server, si_other; int slen , recv_len; char buf[BUFLEN]; WSADATA wsa; slen = sizeof(si_other) ; //Initialise winsock printf("\nInitialising Winsock..."); if (WSAStartup(MAKEWORD(2,2),&wsa) != 0) { printf("Failed. Error Code : %d",WSAGetLastError()); exit(EXIT_FAILURE); } printf("Initialised.\n"); //Create a socket if((s = socket(AF_INET , SOCK_DGRAM , 0 )) == INVALID_SOCKET) { printf("Could not create socket : %d" , WSAGetLastError()); } printf("Socket created.\n"); //Prepare the sockaddr_in structure server.sin_family = AF_INET; server.sin_addr.s_addr = INADDR_ANY; server.sin_port = htons( PORT ); //Bind if( bind(s ,(struct sockaddr *)&server , sizeof(server)) == SOCKET_ERROR) { printf("Bind failed with error code : %d" , WSAGetLastError()); exit(EXIT_FAILURE); } puts("Bind done"); //keep listening for data while(1) { printf("Waiting for data..."); fflush(stdout); //clear the buffer by filling null, it might have previously received data memset(buf,'\0', BUFLEN); //try to receive some data, this is a blocking call if ((recv_len = recvfrom(s, buf, BUFLEN, 0, (struct sockaddr *) &si_other, &slen)) == SOCKET_ERROR) { printf("recvfrom() failed with error code : %d" , WSAGetLastError()); exit(EXIT_FAILURE); } //print details of the client/peer and the data received printf("Received packet from %s:%d\n", inet_ntoa(si_other.sin_addr), ntohs(si_other.sin_port)); printf("Data: %s\n" , buf); //now reply the client with the same data if (sendto(s, buf, recv_len, 0, (struct sockaddr*) &si_other, slen) == SOCKET_ERROR) { printf("sendto() failed with error code : %d" , WSAGetLastError()); exit(EXIT_FAILURE); } } closesocket(s); WSACleanup(); return 0; }', BUFLEN); //try to receive some data, this is a blocking call if ((recv_len = recvfrom(s, buf, BUFLEN, 0, (struct sockaddr *) &si_other, &slen)) == SOCKET_ERROR) { printf("recvfrom() failed with error code : %d" , WSAGetLastError()); exit(EXIT_FAILURE); } //print details of the client/peer and the data received printf("Received packet from %s:%d\n", inet_ntoa(si_other.sin_addr), ntohs(si_other.sin_port)); printf("Data: %s\n" , buf); //now reply the client with the same data if (sendto(s, buf, recv_len, 0, (struct sockaddr*) &si_other, slen) == SOCKET_ERROR) { printf("sendto() failed with error code : %d" , WSAGetLastError()); exit(EXIT_FAILURE); } } closesocket(s); WSACleanup(); return 0; }
To run the above program create a project in VC++ and compile and run. In Vc++ 2010 create an empty project and then add a c file.
The output should be something similar to this
Initialising Winsock...Initialised. Socket created. Bind done Waiting for data...
Test UDP server with netcat
Now this server can be tested with an application called netcat. Over here we shall use the ncat implementation of netcat. It comes with nmap. Download and install nmap. Then do the following in the terminal.
C:\>ncat -vv -u localhost 8888 Ncat: Version 6.01 ( http://nmap.org/ncat ) Ncat: Connected to 127.0.0.1:8888.
So ncat shows that it is connected to our udp server program. The -u option is for udp. Now we can send some data to the server from the ncat terminal which will be echoed back.
C:\>ncat -vv -u localhost 8888 Ncat: Version 6.01 ( http://nmap.org/ncat ) Ncat: Connected to 127.0.0.1:8888. hello hello world world
This is simple. Try it.
Check open port with netstat
The netstat command can be used to check the udp server's open port. Here is a quick example
C:\>netstat -p UDP -a Active Connections Proto Local Address Foreign Address State UDP ----------:microsoft-ds *:* UDP ----------:isakmp *:* UDP ----------:1025 *:* UDP ----------:1037 *:* UDP ----------:1039 *:* UDP ----------:4500 *:* UDP ----------:8888 *:* UDP ----------:17500 *:* UDP ----------:ntp *:* UDP ----------:netbios-ns *:* UDP ----------:netbios-dgm *:* UDP ----------:1900 *:* UDP ----------:ntp *:* UDP ----------:1900 *:* C:\>
Now the line "----------:8888". It is our udp server that is listening on port 8888.
It is interesting to note that the netstat command will not show any connections for any client that is connected to the udp server, for example ncat.
UDP Client
Now that we have tested our server with ncat, its time to make a client program which shall connect to the server and do the same things that the ncat program did earlier.
/* Simple udp client */ #include<stdio.h> #include<winsock2.h> #pragma comment(lib,"ws2_32.lib") //Winsock Library #define SERVER "127.0.0.1" //ip address of udp server #define BUFLEN 512 //Max length of buffer #define PORT 8888 //The port on which to listen for incoming data int main(void) { struct sockaddr_in si_other; int s, slen=sizeof(si_other); char buf[BUFLEN]; char message[BUFLEN]; WSADATA wsa; //Initialise winsock printf("\nInitialising Winsock..."); if (WSAStartup(MAKEWORD(2,2),&wsa) != 0) { printf("Failed. Error Code : %d",WSAGetLastError()); exit(EXIT_FAILURE); } printf("Initialised.\n"); //create socket if ( (s=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == SOCKET_ERROR) { printf("socket() failed with error code : %d" , WSAGetLastError()); exit(EXIT_FAILURE); } //setup address structure memset((char *) &si_other, 0, sizeof(si_other)); si_other.sin_family = AF_INET; si_other.sin_port = htons(PORT); si_other.sin_addr.S_un.S_addr = inet_addr(SERVER); //start communication while(1) { printf("Enter message : "); gets(message); //send the message if (sendto(s, message, strlen(message) , 0 , (struct sockaddr *) &si_other, slen) == SOCKET_ERROR) { printf("sendto() failed with error code : %d" , WSAGetLastError()); exit(EXIT_FAILURE); } //receive a reply and print it //clear the buffer by filling null, it might have previously received data memset(buf,'/* Simple udp client */ #include<stdio.h> #include<winsock2.h> #pragma comment(lib,"ws2_32.lib") //Winsock Library #define SERVER "127.0.0.1" //ip address of udp server #define BUFLEN 512 //Max length of buffer #define PORT 8888 //The port on which to listen for incoming data int main(void) { struct sockaddr_in si_other; int s, slen=sizeof(si_other); char buf[BUFLEN]; char message[BUFLEN]; WSADATA wsa; //Initialise winsock printf("\nInitialising Winsock..."); if (WSAStartup(MAKEWORD(2,2),&wsa) != 0) { printf("Failed. Error Code : %d",WSAGetLastError()); exit(EXIT_FAILURE); } printf("Initialised.\n"); //create socket if ( (s=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == SOCKET_ERROR) { printf("socket() failed with error code : %d" , WSAGetLastError()); exit(EXIT_FAILURE); } //setup address structure memset((char *) &si_other, 0, sizeof(si_other)); si_other.sin_family = AF_INET; si_other.sin_port = htons(PORT); si_other.sin_addr.S_un.S_addr = inet_addr(SERVER); //start communication while(1) { printf("Enter message : "); gets(message); //send the message if (sendto(s, message, strlen(message) , 0 , (struct sockaddr *) &si_other, slen) == SOCKET_ERROR) { printf("sendto() failed with error code : %d" , WSAGetLastError()); exit(EXIT_FAILURE); } //receive a reply and print it //clear the buffer by filling null, it might have previously received data memset(buf,'\0', BUFLEN); //try to receive some data, this is a blocking call if (recvfrom(s, buf, BUFLEN, 0, (struct sockaddr *) &si_other, &slen) == SOCKET_ERROR) { printf("recvfrom() failed with error code : %d" , WSAGetLastError()); exit(EXIT_FAILURE); } puts(buf); } closesocket(s); WSACleanup(); return 0; }', BUFLEN); //try to receive some data, this is a blocking call if (recvfrom(s, buf, BUFLEN, 0, (struct sockaddr *) &si_other, &slen) == SOCKET_ERROR) { printf("recvfrom() failed with error code : %d" , WSAGetLastError()); exit(EXIT_FAILURE); } puts(buf); } closesocket(s); WSACleanup(); return 0; }
The client will ask user to input a message which it will send to the udp server and the udp server shall reply back with the message
Initialising Winsock...Initialised. Enter message : hello hello Enter message : how are you how are you Enter message :
Conclusion
So communication with udp sockets is quite simple. And therefore udp sockets are used where the communication itself is very simple, for example dns requests/response etc.
Or when doing some kind of multicast/broadcast. Where its not a big issue if data fails to transfer, or re-sending the packet is not expensive, udp can be used.
UDP has other benefits as well. Since no connection is established and no verification is done, it uses lesser bandwidth and is faster than TCP.
Hi,
do you have source ?
Thanks,
Chuan
Thanks for this, it’s good to see clean, complete C code for a solid start on new stuff. I’d been looking for NTP code but this is better, more useful for a general base in UDP. (I found a TCP variant of this code elsewhere, last night, same program structure, same port 8888 too. I’m not sure whether that was based on this but it looks like it. That one worked easily when modified to compile with both GCC and TCC with Winsock2 so I know this will too). These small examples are nice for converting to a single thread for a Windows program too. It’s clean enough to make it easy to figure out what to change.
Thanks for writing that article!
Quick notes:
Regarding ncat:
With version 7.93, “ncat -vv -u localhost 8888” translates “localhost” to the value “1”. When sending text , ncat reports…
Ncat: Connected to ::1:8888.
…and subsequently reports a read error, and that the connection was forcibly closed by the remote host.
If you instead use 127.0.0.1 for the server address, everything else works as written above.
FWIW, ncat correctly translates other hostnames to their IP address. So version 7.93 apparently does not handle “localhost” in particular, which is surprising.
Regarding winsock2:
In a source file that includes windows.h, it can be important to include winsock2.h before that, otherwise winsock.h will define symbols that conflict with those in winsock2.h.
I hope that helps.
Thanks again!
Hi,
Very well written, explained and coded. Thank you.
First time that I use UDP to communicate with Arduino as a server and my program on the pc as a client that sends a 2-byte command to the Arduino and it works perfectly.
However. I have a little doubt: once the socket is closed, can I flip the roles? that is, make the arduino as a client and the program as a server to monitor events such as hardware interrupts?.
Maybe by the time you answer I will have solved it, but anyway, thank you very much in advance.
Nice codes, thanks for sharing. I am trying to add checksum for verification.
I thank you very much for this program… very good UPD program…
exacly what i was loking for! perfect.
Hello,
I want to use UDP to communicate between two program (script and SIMULINK) . So I tried to open one Socket (IP (127.0.0.1 ) ,remote address 1234 Local port 25) for transmit and one socket for Receive (IP (127.0.0.1 ) ,remote address 4321 Local port 88).
but when i open two sockets and try a send to im getting a WSAERROR (10047)) .
If i remove the receive socket and try it starts to send .
Can you please help me ??
When I test the code, I find that the SendTo() function can only be executed about 1000 times per second, and how to improve the SendTo() function per second??3Q
Thank you for this tutorial, finally I found working solution.
hi but as i understood there is no need for bind in the UDP protocol we need just to connect and also we can’t use sockaddr_in witch is working only with the TCP/IP protocol
It’s the other way around. The connect() function will return an error on a datagram-type socket like UDP, whereas binding a socket to a hint structure is always required for servers (which is NOT, despite your claim, TCP/IP exclusive).
great example! it is simple and it works out-of-the-box!
this isnt working on two laptops connected via Ethernet. What modifications are required for that ?
#define SERVER “127.0.0.1”
Great….
thankx a lot
How to recvfrom on muliple server ports?? Any ideas plz..
This a great, complete, udp application. Thanks very much.