Segmentation fault reading from HTTP socket - c

I'm writing a simple proxy using socket programming and C.
I have a problem in getting HTTP response from the webserver. When I run this code and try to visit cisco.com website, my program gives me a segmentation fault error.
#include <netinet/in.h>
#include <stdio.h>
#include <string.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netdb.h>
int main()
{
int serverSocket;
char ip[INET_ADDRSTRLEN];
int i;
int j;
serverSocket = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in serverAddress ;
char pageFilter[] = "HTTP/1.1 302 Found\n\n<html><head><title>this web page is filter !..!</title></head><body><h1>This page in filter</h1><p><h3>Please Leave This site and get out of here!</h3></p></body></html>";
serverAddress.sin_family = AF_INET;
serverAddress.sin_port = htons(9090);
bind(serverSocket, (struct sockaddr *)&serverAddress, sizeof(serverAddress));
listen(serverSocket, 20);
while (1)
{
int clientSocket ;
int size;
struct sockaddr_in clientAddress;
char * pch;
char * site;
char buffer[9000];
size = sizeof(clientAddress);
clientSocket = accept(serverSocket, (struct sockaddr *)&clientAddress, &size);
recv(clientSocket, buffer, sizeof(buffer), 0);
site = strstr(buffer, "yahoo.com");
if(site != NULL)
{
send(clientSocket, pageFilter, sizeof(pageFilter) ,0);
close(clientSocket);
}
else
{
int middleSocket;
char buf[128];
char response[10000];
struct sockaddr_in middleAddress;
struct hostent *he;
struct in_addr **addr_list;
char site[] = "cisco.com";
middleSocket = socket(AF_INET, SOCK_STREAM, 0);
middleAddress.sin_family = AF_INET;
middleAddress.sin_port = htons(80);
he = gethostbyname(site);
addr_list = (struct in_addr **)he -> h_addr_list;
middleAddress.sin_addr.s_addr = inet_addr(inet_ntoa(*addr_list[0]));
connect(middleSocket, (struct sockaddr *)&middleAddress, sizeof(middleAddress));
send(middleSocket, buffer, sizeof(buffer),0);
while((unsigned)strlen(buf) != 0)
{
recv(middleSocket, buf, sizeof(buf), 0);
strcat(response,buf);
}
send(clientSocket, response, strlen(response),0);
close(clientSocket);
}
}
return 0;
}

First, capture the return value of recv, which either indicates an error, or the number of bytes received.
ssize_t n;
n = recv(middleSocket, buf, sizeof(buf) - 1);
Note that you shouldn't pass sizeof(buf), since you need room to guarantee zero-termination of buf.
Check for errors.
if (n == -1) { /* handle error */ }
else if (n == 0) { /* handle empty response */ }
And zero-terminate buf.
buf[n] = '\0';
Your segmentation fault is probably occurring because you call strstr on an unbounded string.

A segmentation fault is caused by invalid memory access. Read more: http://en.wikipedia.org/wiki/Segmentation_fault
Use GDB to find the where exactly the program is executing when the error occurs. After this, you should see the problem in your code.

Related

C Socket does not connect and returns exit value of 255

I have a piece of C code that should connect to www.google.com and make a HTTP GET request, but when I run it, it stays on "Connecting.." for about 30 seconds before returning "Connection Failed" and an exit return value of 255. What am I doing wrong?
#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#define PORT 8000
struct hostent *hostinfo;
int main(void) {
int sock = 0, valread;
struct sockaddr_in serv_addr;
char *hostname = "www.google.com";
char *request = "GET / HTTP/1.1\r\nHost: www.google.com\r\n\r\n";
hostinfo = gethostbyname(hostname);
char *ip = inet_ntoa(*(struct in_addr*)hostinfo->h_addr_list[0]);
char buffer[1024] = {0};
printf("Creating socket...\n");
if((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0){
printf("\n Socket creation error \n");
return -1;
}
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(PORT);
printf("Checking address...\n");
if(inet_pton(AF_INET, ip, &serv_addr.sin_addr) <= 0){
printf("\n Invalid IP/Address not supported \n");
return -1;
}
printf("Connecting to host %s...\n", ip);
if(connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0){
printf("\n Connection Failed \n");
return -1;
}
send(sock, request, strlen(request), 0);
printf("Message sent\n");
valread = read(sock, buffer, 1024);
printf("%s\n", buffer);
return 0;
}
I see two major problems.
You use the wrong port. Use port 80 for http.
Your read and printf is a dangerous combination that could easily cause access out of bounds (and undefined behavior). What you read from the socket will not be null terminated. You could instead do something like this:
...
printf("Message sent\n");
while((valread = read(sock, buffer, sizeof(buffer))) > 0) {
fwrite(buffer, valread, 1, stdout);
}
This will however block when everything has been read. See non-blocking I/O or consider using select, epoll or poll to wait for available data on sockets.
If you are only interested in getting the response and then disconnect, you could however use Connection: close to close the connection after the server has sent the response. Full code below:
#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#define PORT 80
int main(void) {
int sock = 0, valread;
struct hostent *hostinfo;
struct sockaddr_in serv_addr;
const char *hostname = "www.google.com";
const char *request = "GET / HTTP/1.1\r\n"
"Host: www.google.com\r\n"
"Connection: close\r\n\r\n"; // <- added
hostinfo = gethostbyname(hostname);
char *ip = inet_ntoa(*(struct in_addr*)hostinfo->h_addr_list[0]);
char buffer[1024] = {0};
printf("Creating socket...\n");
if((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0){
printf("\n Socket creation error \n");
return -1;
}
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(PORT);
printf("Checking address...\n");
if(inet_pton(AF_INET, ip, &serv_addr.sin_addr) <= 0){
printf("\n Invalid IP/Address not supported \n");
return -1;
}
printf("Connecting to host %s...\n", ip);
if(connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0){
perror("connect()");
return -1;
}
send(sock, request, strlen(request), 0);
printf("Message sent\n");
while((valread = read(sock, buffer, sizeof(buffer))) > 0) {
fwrite(buffer, valread, 1, stdout);
}
}

udp socket - bind and connect succeed but send does not work [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I'm trying to communicate through a connected-udp-socket between two peer's. The address information between the peers is transmitted via a server using tcp.
First each peer set's up an udp-socket, binds an address and then transmit the address information via tcp to a server. The server sends the connection information to the other peer.
When the peer receives the information it tries to 'connect' the udp-socket to the other peer. The connect call succeed, but send gives me the following error: 'errno: 89, Destination address required'.
peer.c:
#include "Socket.h"
#include "function.h"
int main (int argc, char** argv) {
if(argc != 4) {
printf("3 Parameter must be given.\nclient-ip server-ip server-port\n");
exit(-1);
}
struct sockaddr_in my_addr, server_addr, other_peer_addr;
address_info* msg_address_info;
header *msg;
int recv_done = 0;
int optval = 1;
int fd_udp, fd_server;
ssize_t len;
socklen_t my_addr_len;
fd_set rfds;
FD_ZERO(&rfds);
fd_udp = Socket(AF_INET, SOCK_DGRAM, 0);
memset((void *) &my_addr, 0, sizeof(my_addr));
my_addr.sin_family = AF_INET;
#ifdef HAVE_SIN_LEN
my_addr.sin_len = sizeof(struct sockaddr_in);
#endif
my_addr.sin_port = 0; // any port
if ((my_addr.sin_addr.s_addr = (in_addr_t)inet_addr(argv[1])) == INADDR_NONE) {
fprintf(stderr, "Invalid address\n");
}
Bind(fd_udp, (const struct sockaddr *) &my_addr, sizeof(my_addr));
Setsockopt(fd_udp, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(int));
Setsockopt(fd_udp, SOL_SOCKET, SO_REUSEPORT, &optval, sizeof(int));
memset((void *) &my_addr, 0, sizeof(my_addr));
my_addr_len = sizeof(my_addr);
//get the current address for server registration
Getsockname(fd_udp, (struct sockaddr *) &my_addr, &my_addr_len);
/* TCP Communication */
/* i use 127.0.0.1:55555 for the server */
fd_server = Socket(AF_INET, SOCK_STREAM, 0);
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
#ifdef HAVE_SIN_LEN
server_addr.sin_len = sizeof(struct sockaddr_in);
#endif
server_addr.sin_port = htons(atoi(argv[3]));
if ((server_addr.sin_addr.s_addr = (in_addr_t) inet_addr(argv[2]))
== INADDR_NONE) {
fprintf(stderr, "Invalid address\n");
}
Connect(fd_server, (const struct sockaddr *) &server_addr, sizeof(server_addr));
len = sizeof(address_info);
msg_address_info = malloc(len + get_padding(len));
memset((void*)msg_address_info, 0, len + get_padding(len));
msg_address_info->head.type = htons(30);
msg_address_info->head.length = htons(sizeof(address_info));
msg_address_info->ip = my_addr.sin_addr.s_addr;
msg_address_info->port = my_addr.sin_port;
Send(fd_server, msg_address_info, len + get_padding(len), 0);
free(msg_address_info);
while(!recv_done) {
FD_ZERO(&rfds);
FD_SET(fd_server, &rfds);
//data is ready for recv
if(FD_ISSET(fd_server, &rfds)) {
msg = recv_stream(fd_server);
if(msg != NULL) {
if(ntohs(msg->type) == 3) {
Close(fd_server);
recv_done = 1;
msg_address_info = (address_info *) msg;
other_peer_addr.sin_addr.s_addr = msg_address_info->ip;
other_peer_addr.sin_port = msg_address_info->port;
}
}
}
}
char buf[512];
memset((void*)&buf, 0, 512);
char* other_peer_ip;
int other_peer_port;
other_peer_ip = inet_ntoa(other_peer_addr.sin_addr);
other_peer_port = ntohs(other_peer_addr.sin_port);
printf("other_peer ip: %s\nother_peer port: %i\n", other_peer_ip, other_peer_port); //matches on bothe peer's
int ret_con = connect(fd_udp, (const struct sockaddr *) &other_peer_addr, sizeof(other_peer_addr));
fprintf(stderr, "ret_con: %i, errno: %i, %s\n", ret_con, errno, strerror(errno));
int ret_send = send(fd_udp, buf, 512, 0);
if(ret_send < 0) {
fprintf(stderr, "ret_send: %i, errno: %i, %s\n", ret_send, errno, strerror(errno));
}
}
function.h:
#define BUFFER_SIZE (1<<16)
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <err.h>
#include <netdb.h>
#include <errno.h>
#include "Socket.h"
typedef struct {
uint16_t type;
uint16_t length;
} header;
typedef struct {
header head;
uint32_t ip;
uint16_t port;
} address_info;
int get_padding(int length);
void* recv_stream(int fd);
functions.c:
#include "functions.h"
void* recv_stream(int fd) {
if(fd < 0) {
fprintf(stderr, "recv_stream: Invaild fd\n");
return NULL;
}
ssize_t len;
int msg_length;
char buf[BUFFER_SIZE];
char* msg;
len = recv(fd, &buf, BUFFER_SIZE, MSG_PEEK);
//Client has closed the connection
if(len <= 0) {
fprintf(stderr, "recv_stream: Client closed the connection.\n");
exit(-1);
}
#ifdef DEBUG
printf("PEEKED %zd bytes.\n", len);
#endif
if(len < sizeof(header)) {
fprintf(stderr, "recv_stream: Message to small no header\n");
return NULL;
}
header *head = (header *) buf;
msg_length = ntohs(head->length);
if(len < msg_length) {
fprintf(stderr, "recv_stream: Message to small\n");
return NULL;
}
else if(len >= msg_length + get_padding(msg_length)) {
msg = malloc(msg_length + get_padding(msg_length));
len = Recv(fd, msg, msg_length + get_padding(msg_length), 0);
head = (header *) msg;
}
return head;
}
int get_padding(int length) {
if(length <= 0) {
fprintf(stderr, "get_padding: wrong length");
}
int pad = length % 4;
if(pad == 3)
pad = 1;
else if(pad == 1)
pad = 3;
return pad;
}
Socket.c with Wrapper functions
int Socket(int fd, int type, int protocol) {
int n;
if((n=socket(fd,type,protocol)) < 0) {
perror("socket");
exit(-1);
}
return n;
}
/* many more */
I read already following question Can you bind() and connect() both ends of a UDP connection but it did not solve my problem.
The transfer of the address information seems to be correct. I printed the send and received addresses on both peers and they match.
I'm stucked on this problem and can't figure out my mistake. Can you help me?
Edit:
provided new example
Now i get the following error:
ret_con: -1, errno: 97, Address family not supported by protocol
ret_send: -1, errno: 89, Destination address required
You are not populating the sin_family field of other_peer_addr before calling connect() on the UDP socket. You are only populating the sin_addr and sin_port fields, which is not enough. connect() needs to be told the type of address being passed to it and that must use the same family as the socket (just like with bind()). Since you are not populating the sin_family field, it contains a random value from the stack, and that is causing connect() to fail with the "Address family not supported" error, and send() cannot be called on an unconnected socket, thus causing the "Destination address required" error.

Multi-threaded TFTP Server - Issue With pthreads

I created a simple tftp server that only handles read requests (RRQ). Everything was working fine until I started to make a multi-threaded version of the server. In the application, I simply receive requests in the main thread and I then forward the request to a new thread that does the packet analysis. Therefore, I need to forward the socket, the received packet and the sockaddr_in struct that contains the client information to the thread. With that said, I created a struct that holds all of these and forward them to the pthread.
I get two identical error messages, one in the main and the other in the connection handler. The problems seems to be in the referencing these variables in the struct and retrieving them in the thread. It seems the problem is in the following statements: in connection_handler(): buffer = cthread->buffer; and in the main(): clientT.buffer = buffer;
Here's the code, I've written so far...
#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <pthread.h>
#define TIMEOUT 5000
#define RETRIES 3
void *connection_handler(void *);
struct clientThread
{
int clientSock;
char opcode;
char buffer[1024];
struct sockaddr_in client;
};
int main()
{
char buffer[1024];
int udpSocket, client_socket, nBytes;
struct sockaddr_in serverAddr, client;
socklen_t addr_size;
udpSocket = socket(AF_INET, SOCK_DGRAM, 0);
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(69);
serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
memset(serverAddr.sin_zero, '\0', sizeof serverAddr.sin_zero);
bind(udpSocket, (struct sockaddr *) &serverAddr, sizeof(serverAddr));
while(1)
{
memset(buffer, 0, 1024);
nBytes = recvfrom(udpSocket,buffer,1024,0,(struct sockaddr *)&client, &addr_size);
// Creating a thread and passing the packet received, the socket and the sockaddr_in struct...
pthread_t client_thread;
struct clientThread clientT;
strcpy(clientT.buffer,buffer);
clientT.clientSock = udpSocket;
clientT.client = client;
pthread_create(&client_thread, NULL, connection_handler, &clientT);
}
return 0;
}
void* connection_handler (void *clientThreaded)
{
char buffer[1024], filename[200], mode[20], *bufindex, opcode;
struct clientThread *cthread = clientThreaded;
int udpSocket = cthread->clientSock;
strcpy(buffer, cthread->buffer);
//opcode = cthread->opcode;
struct sockaddr_in client = cthread->client;
bufindex = buffer;
bufindex++;
// Extracting the opcode from the packet...
opcode = *bufindex++;
// Extracting the filename from the packet...
strncpy(filename, bufindex, sizeof(filename)-1);
bufindex += strlen(filename) + 1;
// Extracting the mode from the packet...
strncpy(mode, bufindex, sizeof(mode)-1);
// If we received an RRQ...
if (opcode == 1)
{
puts("Received RRQ Request");
struct timeval tv;
tv.tv_sec = 5;
char path[70] = "tmp/";
char filebuf [1024];
int count = 0, i; // Number of data portions sent
unsigned char packetbuf[1024];
char recvbuf[1024];
socklen_t recv_size;
socklen_t optionslength = sizeof(tv);
setsockopt(udpSocket, SOL_SOCKET, SO_RCVTIMEO, &tv, optionslength);
FILE *fp;
char fullpath[200];
strcpy(fullpath, path);
strncat(fullpath, filename, sizeof(fullpath) -1);
fp = fopen(fullpath, "r");
if (fp == NULL)
perror("");
memset(filebuf, 0, sizeof(filebuf));
while (1)
{
int acked = 0;
int ssize = fread(filebuf, 1 , 512, fp);
count++;
sprintf((char *) packetbuf, "%c%c%c%c", 0x00, 0x03, 0x00, 0x00);
memcpy((char *) packetbuf + 4, filebuf, ssize);
packetbuf[2] = (count & 0xFF00) >> 8;
packetbuf[3] = (count & 0x00FF);
int len = 4 + ssize;
memset(recvbuf, 0, 1024);
printf("\nSending Packet #%i", count);
sendto(udpSocket, packetbuf, len, 0, (struct sockaddr *) &client, sizeof(client));
for (i=0; i<RETRIES; i++)
{
int result = recvfrom(udpSocket, recvbuf, 1024, 0, (struct sockaddr *) &client, &recv_size);
if ((result == -1) && ((errno == EAGAIN) || (errno == EWOULDBLOCK)))
{
sendto(udpSocket, packetbuf, len, 0, (struct sockaddr *) &client, sizeof(client));
printf("\nRetransmitting Packet #%i", count);
}
else if (result == -1)
{
// Handle Error
}
else
{
acked++;
printf("\nReceived ACK For Data Packet #%i", count);
break;
}
}
if (acked!=1)
{
puts("\nGave Up Transmission After 3 Retries");
break;
}
if (ssize != 512)
break;
}
}
return 0;
}
Thanks in advance :)
In the main loop, the variable clientT is local inside that loop, once the loop iterates the variable will go out of scope and any pointer to it will become invalid. Dereferencing such a pointer will lead to undefined behavior.
Instead what you should to is to dynamically allocate the structure using malloc, and pass that pointer instead. Don't forget to free the structure once you're done with it in the thread.
the current posted code, 7pm PDT,
causes the compiler to emit several warnings
(all of which need to be fixed)
plus some errors.
Errors like: 'buffer = cthread->buffer;'
is copying the address of 'cthread->buffer' to the address of the array 'buffer'.
That probably is not what is wanted.
suggest something similar to: strcpy(buffer, cthread->buffer);
#include <time.h> is missing
so this line: 'struct timeval tv;' is referencing an undefined struct.
The compiler needs to be run with all warnings enabled.
then fix the warnings and the errors.
as a minimum, for gcc, use the parameters:
-Wall -Wextra -Wshadow -pedantic
There are plenty of other error/warning messages that can be enabled
but the above list will catch ~99percent of all errors/warnings
Some googling should find info on how to fix the current errors and warnings.
(although to me, the error/warning messages
make it very clear as to the root cause of the problem.
however, I have been programming for 40 some years)
Each compiler message indicates:
1) which line in the current translation unit (file)
2) and what is wrong with that line.

C socket not running on Mac OS X

The following code runs and communicates with the client without a problem on Ubuntu. However, I need to run on Mac OS X. I can compile it with no errors however when I am trying to run it the following message appears: "Abort trap: 6". I tried to google it but cannot find any useful information about it. Even if I put a printf in the beginning of the main function it does not run. Thank you for any suggestion.
#include <stdio.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#define UNIX_PATH_MAX 108
int connection_handler(int connection_fd)
{
int nbytes;
char buffer[256];
nbytes = read(connection_fd, buffer, 256);
buffer[nbytes] = 0;
printf("MESSAGE FROM CLIENT: %s\n", buffer);
nbytes = snprintf(buffer, 256, "hello from the server");
write(connection_fd, buffer, nbytes);
close(connection_fd);
return 0;
}
int main(void)
{
struct sockaddr_un address;
int socket_fd, connection_fd;
socklen_t address_length;
pid_t child;
socket_fd = socket(PF_UNIX, SOCK_STREAM, 0);
if(socket_fd < 0)
{
printf("socket() failed\n");
return 1;
}
unlink("./demo_socket");
/* start with a clean address structure */
memset(&address, 0, sizeof(struct sockaddr_un));
address.sun_family = AF_UNIX;
snprintf(address.sun_path, UNIX_PATH_MAX, "./demo_socket");
if(bind(socket_fd, (struct sockaddr *) &address, sizeof(struct sockaddr_un)) != 0)
{
printf("bind() failed\n");
return 1;
}
if(listen(socket_fd, 5) != 0)
{
printf("listen() failed\n");
return 1;
}
while((connection_fd = accept(socket_fd, (struct sockaddr *) &address,&address_length)) > -1)
{
child = fork();
if(child == 0)
{
/* now inside newly created connection handling process */
return connection_handler(connection_fd);
}
/* still inside server process */
close(connection_fd);
}
close(socket_fd);
unlink("./demo_socket");
return 0;
}
You have UNIX_PATH_MAX hard-coded to 108, but sun_path in sockaddr_un is only 104 bytes long:
struct sockaddr_un {
unsigned char sun_len; /* sockaddr len including null */
sa_family_t sun_family; /* [XSI] AF_UNIX */
char sun_path[104]; /* [XSI] path name (gag) */
};
So you're trying to write outside the buffer with the following:
snprintf(address.sun_path, UNIX_PATH_MAX, "./demo_socket");
You can fix this with:
snprintf(address.sun_path, sizeof(address.sun_path), "./demo_socket");
This would have been an easy fix if you had used a debugger (such as gdb).
A possible cause is that you don't initialize address_length before calling accept. accept needs it to be properly initialized before the call.

C socket programming, server send buffer seems not to be cleared

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
GET
HEAD
GET
test
GET
, 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);
Your strcmp() in if are wrong
(1) instead of buf you need to compare with result as I can understand from you question, do like: (you says in comment that result printed as GET)
if(strcmp(result, get) == 0){
(2) As #phihag answered it should be
if(strcmp(buf, get) == 0){
^ ^remove &
similar error you have on every strcmp(), because buf, get, head all are charter arrays.
(3) recv() doesn't terminates the read buffer so its better to add null (\0) before you work with it (as i can notice you are using buff as string)
do like:
bytesRec = recv(clientSocket, buf, BUFSIZE, 0);
buf[bytesRec] = '\0'
infect you should read only BUFSIZE-1 bytes left one for null '\0' symbol like:
ytesRec = recv(clientSocket, buf, BUFSIZE-1, 0);
buf[bytesRec] = '\0'

Resources