tcp_udp
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
tcp_udp [2017/05/02 21:05] – [UDP Talker & Listener] dwallace | tcp_udp [2017/05/02 22:45] (current) – dwallace | ||
---|---|---|---|
Line 10: | Line 10: | ||
{{ dylanw: | {{ dylanw: | ||
\\ | \\ | ||
- | The photo above depicts the differences between TCP & UDP connections which allow you to create different forms of communications. The big picture problem is high-latency or low-bandwidth telerobotics. Solving this partially or completely is important because it will allow remote operation of space robotics, disaster relief, etc. This tutorial shows you how to create a TCP client & server, and a UDP talker & listener, and takes approximately | + | The photo above depicts the differences between TCP & UDP connections which allow you to create different forms of communications. The big picture problem is high-latency or low-bandwidth telerobotics. Solving this partially or completely is important because it will allow remote operation of space robotics, disaster relief, etc. This tutorial shows you how to create a TCP client & server, and a UDP talker & listener, and takes approximately |
\\ | \\ | ||
===== Motivation and Audience ===== | ===== Motivation and Audience ===== | ||
Line 93: | Line 93: | ||
==== Server ==== | ==== Server ==== | ||
- | Let's break down the server code. The first block is where we include all the necessary libraries and define essential constants. | + | Let's break down the server code. The server is a program that binds to a certain port, and send a predefined message to any client that connects to it. The first block is where we include all the necessary libraries and define essential constants. |
<code c> | <code c> | ||
Line 254: | Line 254: | ||
Note, don't forget that all of the code after the first two blocks belongs in main( ), and that we must return 0 at the end of main( ). | Note, don't forget that all of the code after the first two blocks belongs in main( ), and that we must return 0 at the end of main( ). | ||
+ | |||
+ | Here is what it looks like when we launch the server: | ||
+ | |||
+ | {{ dylanw: | ||
+ | \\ | ||
+ | And here is what it looks like when something connects to the server: | ||
+ | |||
+ | {{ dylanw: | ||
==== Client ==== | ==== Client ==== | ||
- | Now, let's go over the client. This program is much simpler, as it only need to handle one connection during its run. We start out with the includes and the constant declarations, | + | Now, let's go over the client. The client is a program that connects to server port at a given IP address, and receives the message that the server sends. This program is much simpler, as it only need to handle one connection during its run. We start out with the includes and the constant declarations, |
<code c> | <code c> | ||
Line 373: | Line 381: | ||
Just as with the server, we must ensure that everything after the first two blocks is in the main( ) function, and that we return 0 at the end. | Just as with the server, we must ensure that everything after the first two blocks is in the main( ) function, and that we return 0 at the end. | ||
+ | |||
+ | Here is what it looks like when the client is launched, and receives a message: | ||
+ | |||
+ | {{ dylanw: | ||
+ | |||
===== UDP Talker & Listener ===== | ===== UDP Talker & Listener ===== | ||
Line 380: | Line 393: | ||
[[https:// | [[https:// | ||
+ | |||
+ | ==== Listener ==== | ||
+ | |||
+ | This listener has very similar style to the TCP server we created. The listener is a program that binds to a predefined port, and listens to any messages received on that port, like a " | ||
+ | |||
+ | <code c> | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | |||
+ | #define MYPORT " | ||
+ | |||
+ | #define MAXBUFLEN 100 // The maximum receiving buffer | ||
+ | </ | ||
+ | |||
+ | And again, the get_in_addr function. | ||
+ | |||
+ | <code c> | ||
+ | // Function to get sockaddr, IPv4 or IPv6 | ||
+ | void *get_in_addr(struct sockaddr *sa) | ||
+ | { | ||
+ | if (sa-> | ||
+ | return & | ||
+ | } | ||
+ | |||
+ | return & | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Now, we move onto the main( ) function. We start out with the usual data declarations, | ||
+ | |||
+ | <code c> | ||
+ | int sockfd; // Socket descriptor | ||
+ | struct addrinfo hints, *servinfo, *p; // Used to store IP address info | ||
+ | int rv; // Used for error checking | ||
+ | int numbytes; // Number of bytes received | ||
+ | struct sockaddr_storage their_addr; // Store the talker IP address | ||
+ | char buf[MAXBUFLEN]; | ||
+ | socklen_t addr_len; // IP address length | ||
+ | char s[INET6_ADDRSTRLEN]; | ||
+ | |||
+ | memset(& | ||
+ | hints.ai_family = AF_UNSPEC; // Don't care if IPv4 or IPv6 (set to AF_INET to force IPv4) | ||
+ | hints.ai_socktype = SOCK_DGRAM; // UDP type | ||
+ | hints.ai_flags = AI_PASSIVE; // Use my IP to listen to the socket | ||
+ | |||
+ | if ((rv = getaddrinfo(NULL, | ||
+ | fprintf(stderr, | ||
+ | return 1; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Then we use a for loop to search through the servinfo linked-list, | ||
+ | |||
+ | <code c> | ||
+ | // Loop through all the results and bind to the first we can | ||
+ | for(p = servinfo; p != NULL; p = p-> | ||
+ | if ((sockfd = socket(p-> | ||
+ | p-> | ||
+ | perror(" | ||
+ | continue; | ||
+ | } | ||
+ | |||
+ | if (bind(sockfd, | ||
+ | close(sockfd); | ||
+ | perror(" | ||
+ | continue; | ||
+ | } | ||
+ | |||
+ | break; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Now, we check to see if anything was actually created and bound, and if so, free up the structure and print the waiting message. | ||
+ | |||
+ | <code c> | ||
+ | if (p == NULL) { // If nothing ever bound to the socket | ||
+ | fprintf(stderr, | ||
+ | return 2; | ||
+ | } | ||
+ | |||
+ | freeaddrinfo(servinfo); | ||
+ | |||
+ | printf(" | ||
+ | </ | ||
+ | |||
+ | Finally, we attempt to receive a message, waiting until one is received, and then print where the message was received from, how many bytes were sent, and what the message was. Finally, we close the socket. | ||
+ | |||
+ | <code c> | ||
+ | addr_len = sizeof their_addr; | ||
+ | if ((numbytes = recvfrom(sockfd, | ||
+ | (struct sockaddr *)& | ||
+ | perror(" | ||
+ | exit(1); | ||
+ | } | ||
+ | |||
+ | printf(" | ||
+ | inet_ntop(their_addr.ss_family, | ||
+ | get_in_addr((struct sockaddr *)& | ||
+ | s, sizeof s)); // Print received message and converted IP address | ||
+ | printf(" | ||
+ | buf[numbytes] = ' | ||
+ | printf(" | ||
+ | |||
+ | close(sockfd); | ||
+ | </ | ||
+ | |||
+ | As with the others, make sure to include all of this in main( ), and return 0 at the end. | ||
+ | |||
+ | Here is what it looks like when the listener is launched: | ||
+ | |||
+ | {{ dylanw: | ||
+ | \\ | ||
+ | And here is what it looks like when the listener receives a message: | ||
+ | |||
+ | {{ dylanw: | ||
+ | |||
+ | ==== Talker ==== | ||
+ | |||
+ | The talker is probably the simplest program of all of these, with just 65 lines of code. The talker is a program that send given message to a predefined port on the given IP address. It doesn' | ||
+ | |||
+ | <code c> | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | |||
+ | #define SERVERPORT " | ||
+ | </ | ||
+ | |||
+ | Unlike all of the other programs, no need to define a get_in_addr function, because we are simply sending a UDP packet to the given IP address at the defined port. | ||
+ | |||
+ | So we move onto the main( ) function, with command line arguments. We start off with the usual: declaring structures, checking argument count, filling out the IP address structure, and calling getaddrinfo for the given IP address. | ||
+ | |||
+ | <code c> | ||
+ | int sockfd; // Socket descriptor | ||
+ | struct addrinfo hints, *servinfo, *p; // Structs to store IP address info | ||
+ | int rv; // Error checking | ||
+ | int numbytes; // Number of bytes to send | ||
+ | |||
+ | if (argc != 3) { // Check command line arguments | ||
+ | fprintf(stderr," | ||
+ | exit(1); | ||
+ | } | ||
+ | |||
+ | memset(& | ||
+ | hints.ai_family = AF_UNSPEC; // We don't care if IPv4 or IPv6 (set to AF_INET to force IPv4) | ||
+ | hints.ai_socktype = SOCK_DGRAM; // UDP type | ||
+ | |||
+ | if ((rv = getaddrinfo(argv[1], | ||
+ | fprintf(stderr, | ||
+ | return 1; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Next, we loop through the servinfo linked-list trying to create a socket, and then check if we actually created one. | ||
+ | |||
+ | <code c> | ||
+ | // Loop through all the results and make a socket | ||
+ | for(p = servinfo; p != NULL; p = p-> | ||
+ | if ((sockfd = socket(p-> | ||
+ | p-> | ||
+ | perror(" | ||
+ | continue; | ||
+ | } | ||
+ | |||
+ | break; | ||
+ | } | ||
+ | |||
+ | if (p == NULL) { // Check if anything actually ever was created | ||
+ | fprintf(stderr, | ||
+ | return 2; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Finally, we attempt to send the message packet to the IP address given and the port defined, free the IP address structure, print the message detailing the number of bytes sent, and finally close the socket. | ||
+ | |||
+ | <code c> | ||
+ | if ((numbytes = sendto(sockfd, | ||
+ | | ||
+ | perror(" | ||
+ | exit(1); | ||
+ | } | ||
+ | |||
+ | freeaddrinfo(servinfo); | ||
+ | |||
+ | printf(" | ||
+ | close(sockfd); | ||
+ | </ | ||
+ | |||
+ | As usual, make sure that the code besides the first block is within main( ), with Cl arguments, and you return 0 at the end. | ||
+ | |||
+ | Here is what it looks like when the talker is launched, and sends a message: | ||
+ | |||
+ | {{ dylanw: | ||
+ | This is basically it. Once you understand the basic network calls, and the looping structure, then it should be very easy to implement this yourself. Try out the program given yourself, and then try writing your own, and see if you can make it more efficient, or unique in your own way. Again, this is just the basics, and more difficult concepts will be covered in the future. | ||
===== Final Words ===== | ===== Final Words ===== |
tcp_udp.1493784348.txt.gz · Last modified: 2017/05/02 21:05 by dwallace