Socket Programming: UDP Client Server in C

I am trying to write a client server program using UDP, and wait and stop, but I did not get to this part, I am still trying to understand how these two processes (server and client) are, because in my client program the user needs to enter a name or The IP address of the server, as well as the port name, and then send the expression that the server should evaluate. However, I dug up some tutorials on the Internet and after coding accordingly (or, I thought so), I cannot get the client to communicate with the server. Below is my code, please enlighten me what I am doing wrong if it is bind() , sendto() , recvfrom() or socket() , or all of them. I don’t understand what exactly is wrong. I know that the client side should not work in an infinite loop, but so far I want the programs to exchange data with each other, after which I will polish my code. Thanks!

client code:

 #include <stdio.h> // Default System Calls #include <stdlib.h> // Needed for OS X #include <string.h> // Needed for Strlen #include <sys/socket.h> // Needed for socket creating and binding #include <netinet/in.h> // Needed to use struct sockaddr_in #include <time.h> // To control the timeout mechanism #define EXPR_SIZE 1024 #define BUFLEN 512 #define TRUE 1 #define FALSE 0 #define SERVERLEN 1024 int main(int argc, char **argv){ long portNum; // Since it possible to input a value bigger // than 65535 we'll be using long to // avoid overflows char expr[EXPR_SIZE]; char server[SERVERLEN]; int fd; // file descriptor for the connected socket int buf[512]; struct hostent *h; // information of the host unsigned int addrLen; // address length after getting the port number struct sockaddr_in myaddr; // address of the client struct sockaddr_in servaddr; // server address unsigned int exprLen; socklen_t slen = sizeof(servaddr); printf("Enter server name or IP address:"); scanf("%s",server); printf("Enter port:"); scanf("%ld",&portNum); if ((portNum < 0) || (portNum > 65535)) { printf("Invalid port number. Terminating."); return 0; } printf("Enter expression:"); scanf("%s",expr); if((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0){ perror("cannot create socket"); return 0; } memset((char *)&myaddr, 0, sizeof(myaddr)); myaddr.sin_family = AF_INET; myaddr.sin_addr.s_addr = htonl(INADDR_ANY); myaddr.sin_port = htons(0); if(bind(fd, (struct sockaddr *)&myaddr, sizeof(myaddr)) < 0){ perror("cannot bind"); return 0; } /* // Discovering the port number the OS allocated addrLen = sizeof(myaddr); if(getsockname(fd, (struct sockaddr *)&myaddr, &addrLen) < 0){ perror("cannot getsockname"); return 0; } printf("local port number = %d\n", ntohs(myaddr.sin_port)); */ memset((char*)&servaddr, 0, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_port = htonl(portNum); exprLen = sizeof(expr); while(TRUE){ printf("Sending message to %s port %ld\n",server, portNum); if (sendto(fd, expr, strlen(expr), 0, (struct sockaddr *)&servaddr, slen) < 0) { perror("cannot sendto()"); } printf("Success\n"); } return 0; } 

Server Side Code:

 #include <stdio.h> // Default System Calls #include <stdlib.h> // Needed for OS X #include <string.h> // Needed for Strlen #include <sys/socket.h> // Needed for socket creating and binding #include <netinet/in.h> // Needed to use struct sockaddr_in #include <time.h> // To control the timeout mechanism #define EXPR_SIZE 1024 #define BUFLEN 512 #define TRUE 1 #define SERVERLEN 1024 int main(int argc, char **argv){ struct sockaddr_in myaddr; // address of the server struct sockaddr_in claddr; // address of the client char buf[BUFLEN]; int fd; long recvlen; socklen_t clientlen; if((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0){ perror("cannot create socket"); return 0; } memset((char *)&myaddr, 0, sizeof(myaddr)); myaddr.sin_family = AF_INET; myaddr.sin_addr.s_addr = htonl(INADDR_ANY); myaddr.sin_port = htons(0); if(bind(fd, (struct sockaddr *)&myaddr, sizeof(myaddr)) < 0){ perror("cannot bind"); return 0; } clientlen = sizeof(claddr); while (TRUE) { recvlen = recvfrom(fd, buf, BUFLEN, 0, (struct sockaddr *)&claddr, &clientlen); if (recvlen < 0) { perror("cannot recvfrom()"); return 0; } printf("Received %ld bytes\n",recvlen); buf[recvlen] = 0; printf("Received message: \"%s\"\n",buf); } return 0; } 

The server program does not output anything, and the client issues until the process is interrupted:

 Enter server name or IP address:127.0.0.1 Enter port:30 Enter expression:2+2 Sending message to 127.0.0.1 port 30 cannot sendto(): Can't assign requested address 

I tried changing the server name to localhost and other ports, but to no avail.

+6
source share
1 answer

When developing network software (especially when using the BSD socket interface), it is important to keep everything as simple as possible until you have established a basic connection. Then you can gradually add functionality, ensuring that you don't break anything along the way.

On the client side, simplifying things means

  • Do not call bind in the client. The OS will select the appropriate interface and assign an arbitrary port number, so there is no need for a bind socket.

  • Use a hard-coded server address (for example, 127.0.0.1). The address 127.0.0.1 (0x7f000001) is the address of the local host, suitable for sending packets to the server on one computer.

  • Use a hard port number (for example, 50037). Ephemeral port numbers must be greater than 0xC000 hex (49152 decimal).

  • Use a hard-coded message, for example. "Hello".

With that in mind, this is what client software looks like

 int main( void ) { int fd; if ( (fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) { perror("socket failed"); return 1; } struct sockaddr_in serveraddr; memset( &serveraddr, 0, sizeof(serveraddr) ); serveraddr.sin_family = AF_INET; serveraddr.sin_port = htons( 50037 ); serveraddr.sin_addr.s_addr = htonl( 0x7f000001 ); for ( int i = 0; i < 4; i++ ) { if (sendto( fd, "hello", 5, 0, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) < 0 ) { perror( "sendto failed" ); break; } printf( "message sent\n" ); } close( fd ); } 

Server Side Saving Simple Things

  • Bind to INADDR_ANY , i.e. let the OS choose the appropriate interface.
  • Bind to a hard-coded port, for example. 50037 (must be the same port that the client uses).
  • Do not request address information from recvfrom , i.e. pass NULL, 0 as the last two parameters.

With this in mind, what server software looks like

 int main( void ) { int fd; if ( (fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) { perror( "socket failed" ); return 1; } struct sockaddr_in serveraddr; memset( &serveraddr, 0, sizeof(serveraddr) ); serveraddr.sin_family = AF_INET; serveraddr.sin_port = htons( 50037 ); serveraddr.sin_addr.s_addr = htonl( INADDR_ANY ); if ( bind(fd, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) < 0 ) { perror( "bind failed" ); return 1; } char buffer[200]; for ( int i = 0; i < 4; i++ ) { int length = recvfrom( fd, buffer, sizeof(buffer) - 1, 0, NULL, 0 ); if ( length < 0 ) { perror( "recvfrom failed" ); break; } buffer[length] = '\0'; printf( "%d bytes: '%s'\n", length, buffer ); } close( fd ); } 
+12
source

All Articles