I've written a simple Linux Client - Server connection that sends a string from server to client, client prints string. The client then sends a String to the server, the server prints the String
I run my code in a Linux virtual machine, The distro is Debian.
What's happening is when the client prints the string, the program behaves normally, however when the server prints the string in the same way, it prints the string then on the next line adds garbage data such as ♦.
I've looked hard at all the pointers and writes to see if I have any buffer overflows which would cause this problem, however I am new to c and cannot find any myself.
Whats wierd about the error is it only happens in server and never in client even though they print the string exactly the same way.
As stated before I've looked line by line searching for buffer overflows, as well as looking at other peoples problems. I've tried using fflush(stdout) and messing with pointers but nothing I've tried works.
Removing the ".*" in server printf() results in a segfault
This is the client Code
#include <stdio.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <string.h>
#include <unistd.h>
int main() {
//create server info
struct sockaddr_in server_info = {0};
server_info.sin_family = AF_INET;
server_info.sin_addr.s_addr = htonl(0x7f000001);
server_info.sin_port = htons(25565);
socklen_t server_info_len = sizeof(server_info);
//create client socket
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
perror("socket");
return -1;
}
//connect to server
if (connect(sockfd, (struct sockaddr*)&server_info, server_info_len) < 0) {
perror("connect");
return -1;
}
char buffer[1024];
//recieve message
ssize_t recvd = recv(sockfd, buffer, sizeof(buffer)-1, 0);
if (recvd < 0) {
perror("recv");
return -1;
}
//print message
printf("%.*s", sizeof(buffer)-1, buffer);
//send client message
char* sentFromClient = "Sent from client!\n";
ssize_t sent = send(sockfd, (void*)sentFromClient, strlen(sentFromClient), 0);
if (sent < 0) {
perror("send");
return -1;
}
//close socket
if (close(sockfd) < 0) {
perror("close");
return -1;
}
return 0;
}
This is the Server Code
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
int main() {
//create server structures
struct sockaddr_in server_info = {0};
server_info.sin_family = AF_INET;
server_info.sin_port = htons(25565);
socklen_t server_info_len = sizeof(server_info);
//create client structures for server use
struct sockaddr client_info = {0};
socklen_t client_info_len = sizeof(client_info);
//create our socket
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
perror("socket");
return -1;
}
//bind socket
if (bind(sockfd, (struct sockaddr*)&server_info, server_info_len) < 0) {
perror("bind");
return -1;
}
//listen on port
if (listen(sockfd, 0) < 0) {
perror("listen");
return -1;
}
//accept client
int clientfd = accept(sockfd, &client_info, &client_info_len);
if (clientfd < 0) {
perror("accept");
return -1;
}
//send client message
char* sentViaServer = "From Server!\n";
ssize_t sent = send(clientfd, (void*)sentViaServer, strlen(sentViaServer), 0);
if (sent < 0) {
perror("send");
return -1;
}
//recieve client message
char buffer[1024];
ssize_t recvd = recv(clientfd, buffer, sizeof(buffer)-1, 0);
if (recvd < 0) {
perror("recv");
return -1;
}
//print client message
printf("%.*s", sizeof(buffer)-1, buffer);
//close socket
if (close(clientfd) < 0) {
perror("close");
return -1;
}
if (close(sockfd) < 0) {
perror("close");
return -1;
}
return 0;
}
These are the outputs of Server and Client respectively
CodePudding user response:
In both the client and server, you're sending exactly as many characters as are in their respective strings. This does not include a terminating null byte. And because the buffer in both the client and server are uninitialized, after you read in the string that was sent and attempt to print it, you end up reading uninitialized values in each buffer. On the client it happens to not show anything, presumably because some of those uninitialized bytes happened to be 0, but that isn't the case on the server side.
You can handle this by either sending the terminating null byte in both cases:
// client
ssize_t sent = send(sockfd, sentFromClient, strlen(sentFromClient) 1, 0);
// server
ssize_t sent = send(clientfd, sentViaServer, strlen(sentViaServer) 1, 0);
Or by terminating the string manually after reading.
// client and server
if (recvd < 0) {
perror("recv");
return -1;
}
buffer[recvd] = 0;