I've created an account just for this since I'm at my wits end here: The goal is for the server to receive and read exactly 2 bytes from the message "Hello from client" - 1 byte at a time with recvfrom(). This doesn't work - the first recvfrom() makes the program sleep indefinitely (I haven't set a timeout in purpose). For the record I am using a Linux (Ubuntu) virtual machine with Oracle VM VirtualBox, and I'm fairly new to programming in C. udp_server.c and udp_client.c codes pasted below, would appreciate any insight.
udp_server.c:
int main(void) {
/* Socket */
int sock = socket(AF_INET, SOCK_DGRAM, 0);
if (sock == -1) {
perror("socket(2)");
return 1;
}
/* Set socket option SO_REUSEADDR */
int opt = 1;
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0) {
perror("setsockopt(2)");
close(sock);
return 1;
}
/* server sockaddr_in struct */
struct sockaddr_in server;
memset(&server, 0, sizeof(server));
server.sin_addr.s_addr = INADDR_ANY;
server.sin_family = AF_INET;
server.sin_port = htons(5061);
/* Bind */
if (bind(sock, (struct sockaddr*)&server, sizeof(server)) < 0) {
perror("bind(2)");
close(sock);
return 1;
}
/* client sockaddr_in struct (for recvfrom()) */
struct sockaddr_in client;
socklen_t client_len = sizeof(client);
memset(&client, 0, sizeof(client));
/* Receive data from socket */
fprintf(stdout, "Listening on port %d...\n", 5061);
char buffer[1024] = { 0 };
int bytes_received = recvfrom(sock, buffer, 1, 0, (struct sockaddr*)&client, &client_len);
// PROGRAM FREEZES HERE ^^^
if (bytes_received < 0) {
printf("bytes_received %d, errno %d", bytes_received, errno);
perror("recvfrom");
close(sock);
return 1;
}
printf("SUCCESS(1) bytes_received %d", bytes_received);
bytes_received = recvfrom(sock, buffer, 1, 0, (struct sockaddr*)&client, &client_len);
if (bytes_received < 0) {
printf("bytes_received %d, errno %d", bytes_received, errno);
perror("recvfrom");
close(sock);
return 1;
}
printf("SUCCESS(2) bytes_received %d", bytes_received);
/* Shutdown */
shutdown(sock, SHUT_RDWR);
close(sock);
return 0;
}
udp_client.c:
int main(void) {
/* Socket */
int sock = socket(AF_INET, SOCK_DGRAM, 0);
if (sock == -1) { // In case socket creation failed.
fprintf(stdout, "ERROR: Socket creation failed.\n");
return -1;
}
/* Server sockaddr_in struct (for sendto()) */
struct sockaddr_in server;
memset(&server, 0, sizeof(server));
server.sin_family = AF_INET;
server.sin_port = htons(5061);
if (inet_pton(AF_INET, "127.0.0.1", &server.sin_addr) <= 0) {
perror("inet_pton(3)");
close(sock);
return 1;
}
/* Send data to socket */
char* message = "Hello from client";
int bytes_sent = sendto(sock, message, strlen(message), 0, (struct sockaddr*)&server, sizeof(server));
if (bytes_sent <= 0) {
perror("sendto(2)");
close(sock);
return 1;
}
fprintf(stdout, "Sent %d bytes to %s:%d - %s\n",
bytes_sent, inet_ntoa(server.sin_addr), ntohs(server.sin_port), message);
usleep(75000);
/* Shutdown */
shutdown(sock, SHUT_RDWR);
close(sock);
return 0;
}
The
udp_clientprogram sends a 17-byte datagram to theudp_serverprogram, which is expecting two datagrams of 1 byte each. The 16 excess bytes from the first datagram will be discarded.If the
udp_clientprogram is run twice, then two 17-byte datagrams will be sent to theudp_serverprogram. The 16 excess bytes from each received datagram will be discarded, soudp_serverwill write the following to the standard output stream as a result of reading the two datagrams:Note: there is no newline after the output. The only
printfcall in "udp_server.c" that includes a newline character at the end of the format string is the one that prints theListening on port 5061...message. If the standard output stream is line buffered, the output from the otherprintfcalls will remain buffered until the program exits, when the buffered contents will be output to the terminal.For Unix, the usual convention is to initialize the standard input, standard output, and standard error streams as follows: