I am very new to socket programming and I have troubles with it. I want to implement a server that answers depending on a certain client request. In my case, either GET, HEAD or an error else. Consider following code
If I print the answer before calling send() (see server side code below), the message is correct. But let's say from the client I send
, the answer printed from the client side is
You want GET
You want HEAD
You want GETD
HTTP/1.1 400 Bad Request
You want GET Bad Request
So it seems like that the message sent from the server is kind of 'overwritten', but how is this avoidable? Is it possible to 'clear the server buffer' if that is the problem at all?
Here is the full server side code
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#define BUFSIZE 1024
#define MAXPENDING 100
int main(){
char get[] = "GET";
char head[] = "HEAD";
int serverSocket = socket(PF_INET, SOCK_STREAM, 0);
struct sockaddr_in serverAddress;
serverAddress.sin_family = AF_INET;
serverAddress.sin_port = htons(8080);
serverAddress.sin_addr.s_addr = htonl(INADDR_ANY);
memset(&serverAddress.sin_zero, '\0', 8);
bind(serverSocket, (struct sockaddr*)&serverAddress, sizeof(serverAddress));
listen(serverSocket, MAXPENDING);
for(;;){
struct sockaddr_in clientAddress;
int clientAddressLength = sizeof(clientAddress);
int clientSocket;
clientSocket = accept(serverSocket, (struct sockaddr*)&clientAddress, &clientAddressLength);
char buf[BUFSIZE];
int bytesRec;
bytesRec = recv(clientSocket, buf, BUFSIZE, 0);
while(bytesRec > 0){
char *result;
result = strtok(buf, " ");
printf("result %s\n", result);
if(strcmp(&buf, &get) == 0){
char answer[] = "You want GET";
send(clientSocket, answer, strlen(answer), 0);
}else{
if(strcmp(&buf, &head) == 0){
char answer[] = "You want HEAD";
send(clientSocket, answer, strlen(answer), 0);
}else{
char answer[] = "HTTP/1.1 400 Bad Request";
send(clientSocket, answer, strlen(answer), 0);
}
}
bytesRec = recv(clientSocket, buf, BUFSIZE, 0);
}
return 0;
}
and the client side
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
int main(){
int clientSocket = socket(PF_INET, SOCK_STREAM, 0);
struct sockaddr_in clientAddress;
clientAddress.sin_family = AF_INET;
clientAddress.sin_port = 0;
clientAddress.sin_addr.s_addr = htonl(INADDR_ANY);
memset(&clientAddress.sin_zero, '\0', 8/*sizeof(clientAddress.sin_zero)*/);
bind(clientSocket, (struct sockaddr*)&clientAddress, sizeof(clientAddress));
struct sockaddr_in serverAddress;
serverAddress.sin_family = AF_INET;
serverAddress.sin_port = htons(8080);
serverAddress.sin_addr.s_addr = inet_addr("127.0.0.1");
memset(&serverAddress.sin_zero, '\0', 8);
if(connect(clientSocket, (struct sockaddr*)&serverAddress, sizeof(serverAddress)) == -1){
printf("error in connecting!\n");
return 0;
}
char* serverReply[1024];
for(;;){
char request[100];
printf("Enter your request: ");
scanf("%s", &request);
send(clientSocket, request, strlen(msg), 0);
if(recv(clientSocket, serverReply, strlen(serverReply), 0) < 0){
printf("failure in receiving from server!\n");
}else{
printf("%s\n", serverReply);
}
}
close(clientSocket);
return 0;
}
send(clientSocket, request, strlen(msg), 0);
This sends only the string characters and does not include the terminating NULL. The receive buffer does not terminate the received string on the server side.
This is why you are still seeing the 'D' character from the previous message.
You want GETD <-- 'D' is from the previous 'HEAD'
Either terminate the received string on the server,
buf[bytesRec] = '\0';
Edit: as @Zan points out, don't do this:
or send the NULL terminator from the client.
send(clientSocket, request, strlen(msg) + 1, 0);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With