Related
I have been trying to get this FTP client/ server to work together but its currently not playing friendly
Bits of code that I have tested and that I couldn't find to work have been commented but also some of these commented recv and write lines work but to make the over all problem simpler i have commented them out for the time being. The problem seems to be in the ConnectionHandler function under the else if(strstr(client_request, "Put")) line of code. i have currently got successful FTP from the server to the client but the client to server part I'm struggling to get to work any advice would be grateful.
I feel as though this line is the problem file_desc = open(file_name, O_CREAT | O_EXCL | O_WRONLY, 0777); but i need to create the file to run to but file_desc returns -1 even though the file is created and I'm simply unable to determine why this is the case. Ultimately i may be overlooking something else.
Server
/*
* Compile & link : gcc server.c -lpthread -o server
* Execute : ./server
*/
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/sendfile.h>
#include <fcntl.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdbool.h>
#include <pthread.h>
#define SERVER_PORT 8080
void* ConnectionHandler(void* socket_desc);
char* GetFilenameFromRequest(char* request);
bool SendFileOverSocket(int socket_desc, char* file_name);
int readn(int fd, char *buf, int bufsize)
{
short data_size; // sizeof (short) must be 2
int n, nr, len;
// check buffer size len
if (bufsize < BUFSIZ)
return (-3); // buffer too small
// get the size of data sent to me
if (read(fd, (char *) &data_size, 1) != 1)
return (-1);
if (read(fd, (char *) (&data_size)+1, 1) != 1)
return (-1);
len = (int) ntohs(data_size); // convert to host byte order
// read len number of bytes to buf
for (n=0; n < len; n += nr)
{
if ((nr = read(fd, buf+n, len-n)) <= 0)
return (nr); // error in reading
}
return (len);
}
int main(int argc, char **argv)
{
int socket_desc,
socket_client,
*new_sock,
c = sizeof(struct sockaddr_in);
struct sockaddr_in server,
client;
// Create socket
socket_desc = socket(AF_INET, SOCK_STREAM, 0);
if (socket_desc == -1)
{
perror("Could not create socket");
return 1;
}
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons(SERVER_PORT);
if (bind(socket_desc, (struct sockaddr *)&server, sizeof(server)) < 0)
{
perror("Bind failed");
return 1;
}
listen(socket_desc , 3);
while (socket_client = accept(socket_desc, (struct sockaddr *)&client, (socklen_t*)&c))
{
pthread_t sniffer_thread;
new_sock = malloc(1);
*new_sock = socket_client;
pthread_create(&sniffer_thread, NULL, ConnectionHandler, (void*) new_sock);
pthread_join(sniffer_thread, NULL);
}
if (socket_client<0)
{
perror("Accept failed");
return 1;
}
return 0;
}
void *ConnectionHandler(void *socket_desc)
{
int socket = *(int*)socket_desc;
char server_response[BUFSIZ],
client_request[BUFSIZ],
file_name[BUFSIZ];
recv(socket, client_request, BUFSIZ, 0); //Wait at this point to recieve a message from the client
if(strstr(client_request, "Get"))
{
perror("1");
strcpy(file_name, GetFilenameFromRequest(client_request));
// If requested file exists, notify the client and send it
if (access(file_name, F_OK) != -1){
perror("2");
strcpy(server_response, "OK");
write(socket, server_response, strlen(server_response));
perror("3");
SendFileOverSocket(socket, file_name);
perror("4");
}
else {
// Requested file does not exist, notify the client
strcpy(server_response, "NO");
write(socket, server_response, strlen(server_response));
}
}
else if(strstr(client_request, "Put"))
{
char *data, reply_msg[BUFSIZ];
char buff[BUFSIZ];
int file_size, file_desc;
perror("0.5");
strcpy(file_name, GetFilenameFromRequest(client_request));
perror("0.75");
//recv(socket, reply_msg, 2, 0); //Receive reply message from client if file exists
//fprintf(stderr, "File was found = %s", reply_msg);
//Create File
perror("1");
recv(socket, &file_size, sizeof(int), 0);
perror("1.25");
file_desc = open(file_name, O_CREAT | O_EXCL | O_WRONLY, 0666);
perror("1.5");
int incomingSize;
while((incomingSize = readn(socket, buff, sizeof(buff))) > 0)
{
perror("2 ");
for(int i = 0; i <= sizeof(buff); i++)
{
buff[incomingSize] = '\0';
write(file_desc, buff, sizeof(buff));
}
}
perror("3");
if(incomingSize < 0)
{
perror("Something went wrong connection broken");
return; // connection broken down
}
else
{
fprintf(stderr, "Connection terminated");
}
perror("4");
close(socket);
/*
perror("1");
data = malloc(BUFSIZ);
file_desc = open(file_name, O_CREAT | O_EXCL | O_WRONLY, 0777);
perror("1.2");
fprintf(stderr, "fileDesc = %d", file_desc);
perror("1.5");
strcpy(server_response, "OK");
write(socket, server_response, strlen(server_response));
perror("2");
//recv(socket, &file_size, sizeof(int), 0);
perror("3");
//recv(socket, &file_size, sizeof(int), 0);
file_size = BUFSIZ;
perror("4");
fprintf(stderr, "%d", file_size);
recv(socket, data, file_size, 0);
perror("5");
write(file_desc, data, file_size);
perror("6");
close(file_desc);
*/
/*// Start receiving file
if (strcmp(reply_msg, "OK") == 0) //Check that response is "OK"
{
}
else
{
fprintf(stderr, "Bad request\n");
}
*/
}
free(socket_desc);
return 0;
}
char* GetFilenameFromRequest(char* request)
{
char *file_name = strchr(request, ' ');
return file_name + 1;
}
bool SendFileOverSocket(int socket_desc, char* file_name)
{
struct stat obj;
int file_desc,
file_size;
stat(file_name, &obj);
file_desc = open(file_name, O_RDONLY);
file_size = obj.st_size;
send(socket_desc, &file_size, sizeof(int), 0);
sendfile(socket_desc, file_desc, NULL, file_size);
return true;
}
Client
/*
* Compile & link : gcc client.c -o client
* Execute : ./client
*
*/
#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/stat.h>
#include <sys/sendfile.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#define FILENAME "a.txt" //Possibly worth changing to make it more dynamic
//Should consider overriding this with command line arguments if passed
#define SERVER_IP "127.0.0.1" //Address of local host
#define SERVER_PORT 8080
bool SendFileOverSocket(int socket_desc, char* file_name);
int writen(int fd, char *buf, int nbytes)
{
short data_size = nbytes; // short must be two bytes long
int n, nw;
if (nbytes > BUFSIZ)
return (-3); // too many bytes to send in one go
// send the data size
data_size = htons(data_size);
if (write(fd, (char *) &data_size, 1) != 1)
return (-1);
if (write(fd, (char *) (&data_size)+1, 1) != 1)
return (-1);
// send nbytes
for (n=0; n<nbytes; n += nw)
{
if ((nw = write(fd, buf+n, nbytes-n)) <= 0)
return (nw); // write error
}
return (n);
}
int main(int argc , char **argv)
{
int socket_desc;
// Variables for the file being received
int file_size, file_desc;
struct sockaddr_in server;
char request_msg[BUFSIZ],
reply_msg[BUFSIZ],
userCommand[BUFSIZ],
userFileName[BUFSIZ],
*data;
socket_desc = socket(AF_INET, SOCK_STREAM, 0);
if (socket_desc == -1)
{
perror("Could not create socket");
return 1;
}
server.sin_addr.s_addr = inet_addr(SERVER_IP);
server.sin_family = AF_INET;
server.sin_port = htons(SERVER_PORT);
// Connect to server
if (connect(socket_desc, (struct sockaddr *)&server, sizeof(server)) < 0)
{
perror("Connection failed");
return 1;
}
printf("------------Enter Command-----------\n");
printf("Get, Put, Pwd, lpwd, dir, ldir, cd, lcd, quit\n");
printf("------------------------------------\n");
while(userCommand != "quit")
{
printf(">");
fgets(userCommand, BUFSIZ, stdin);
printf("User Command Variable = %s", userCommand);
if(strstr(userCommand, "Get"))
{
char userFileName[BUFSIZ];
// Get a file from server
strcpy(request_msg, "Get "); //Copy message "Get " into variable request_msg
printf("Enter the file name you would like to send.");
scanf("%s", userFileName);
strcat(request_msg, userFileName); //Add the file name to the end of the varaible that is now "Get "
printf("1");
write(socket_desc, request_msg, strlen(request_msg)); //Changing this to fwrite produces same results with more warnings
printf("2");
recv(socket_desc, reply_msg, 2, 0); //Wait here for response
printf("3");
// Start receiving file
if (strcmp(reply_msg, "OK") == 0) //Check that response is "OK"
{
printf("4");
recv(socket_desc, &file_size, sizeof(int), 0);
printf("5");
data = malloc(file_size);
file_desc = open(userFileName, O_CREAT | O_EXCL | O_WRONLY, 0666);
recv(socket_desc, data, file_size, 0);
printf("6");
write(file_desc, data, file_size);
printf("7");
close(file_desc);
}
else
{
fprintf(stderr, "Bad request\n");
}
}
else if(strstr(userCommand, "Put"))
{
char server_response[BUFSIZ], buff[BUFSIZ];
struct stat obj;
fprintf(stderr,"What is the file name you would like to send?\n");
scanf("%s", userFileName);
fprintf(stderr,"File name entered was: %s", userFileName);
strcpy(request_msg, "Put "); //Copy message "Get " into variable request_msg
strcat(request_msg, userFileName); //Add the file name to the end of the varaible that is now "Get "
perror("1");
write(socket_desc, request_msg, strlen(request_msg)); //Changing this to fwrite produces same results with more warnings
perror("2");
stat(userFileName, &obj);
file_desc = open(userFileName, O_RDONLY);
file_size = obj.st_size;
perror("2.1");
strcpy(reply_msg, "OK");
perror("2.2");
//write(socket_desc, reply_msg, strlen(reply_msg));
perror("2.3");
perror("2.4");
perror("2.45");
writen(socket_desc, buff, sizeof(buff));
//SendFileOverSocket(socket_desc, userFileName);
perror("3");
close(socket_desc);
/*if (access(userFileName + 1, F_OK) != -1)
{
}
else {
printf("File doesnt exist with access code %d\n", access(userFileName, F_OK));
strcpy(reply_msg, "OK");
write(socket, reply_msg, strlen(reply_msg));
}*/
}
}
return 0;
}
/*bool SendFileOverSocket(int socket_desc, char* file_name)
{
struct stat obj;
int file_desc,
file_size;
stat(file_name, &obj);
file_desc = open(file_name, O_RDONLY);
file_size = obj.st_size;
printf("2.5");
printf("%s", file_name);
//send(socket_desc, &file_size, sizeof(int), 0);
printf("2.6");
perror("Pre");
sendfile(socket_desc, file_desc, NULL, file_size);
perror("sendfile");
printf("2.7");
return true;
}*/
I'm working on a TCP client server program which is supposed to support several clients using threads.
The socket creation, connection, bind and accept work as expected since I receive no errors when running the code.
However whenever I try to read() from the server the code enters an infinite loop and nothing happens.
I tried writing from the server first and the write result was written to the server's terminal.
Client code:
#include <stdlib.h>
#include <stdio.h>
#include <stdio.h>
#include <unistd.h>
#include <assert.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <dirent.h>
#define FILE_ADDR "/dev/urandom"
int main(int argc, char *argv[]) {
//Get command line arguments
unsigned int port = atoi(argv[2]);
int length = atoi(argv[3]); //Number of bytes to read
char* buffer = malloc(length * sizeof(char)); //Buffer to hold data read from file
char* recvBuf = malloc(10 * sizeof(char)); // Buffer to hold response from server
struct addrinfo hints, *servinfo, *p;
struct sockaddr_in serv_addr;
int sockfd = -1;
//int rv;
//char ip[100];
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
int rv = getaddrinfo(argv[1], argv[2], &hints, &servinfo);
if (rv != 0) {
perror("getaddrinfo error\n");
exit(1);
}
for (p = servinfo; p != NULL; p = p->ai_next) {
//Initialize socket
sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
if (sockfd < 0)
continue;
//Initialize connection
rv = connect(sockfd, p->ai_addr, (socklen_t) p->ai_addrlen);
if (rv == 0)
break;
close(sockfd);
sockfd = -1;
}
// inet_aton(ip, &h.sin_addr);
freeaddrinfo(servinfo);
//Open file for reading
FILE *fp;
fp = fopen(FILE_ADDR, "r");
if (fp == NULL) {
perror("Error in file open\n");
}
printf("file opened\n");
size_t numOfbytesRead = fread(buffer, sizeof(char), length, fp);
if (numOfbytesRead != length) {
perror("Error reading from file\n");
}
printf("Buffer is %s\n", buffer);
char* ptr;
unsigned int N = strtoul(argv[3],&ptr,10);
int convertedNum = htonl(N);
if (write(sockfd, &convertedNum, sizeof(unsigned int)) < 0) { //Send number of bytes
perror("error writing to socket");
}
if (write(sockfd, buffer, sizeof(buffer) < 0)) {//Send bytes read from file
perror("error writing to socket");
}
printf("send is done \n");
int bytes_read = read(sockfd, recvBuf, sizeof(recvBuf)); //Recieve response from server
if (bytes_read <= 0) {
perror("Error in recieving result from server\n");
}
unsigned int C = 0;
sprintf(recvBuf[0], "%d", C);
fclose(fp);
printf("# of printable characters: %u\n", C);
exit(0);
free(buffer);
free(recvBuf);
}
Server code:
#include <stdlib.h>
#include <stdio.h>
#include <stdio.h>
#include <unistd.h>
#include <assert.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <dirent.h>
#include <pthread.h>
#include <signal.h>
static volatile int keepRunning = 1;
int pcc_total[159];
void intHandler(int dummy) {
keepRunning = 0;
}
void *compute(void *socket_desc) {
int count = 0;
int sock = *(int*) socket_desc;
printf("now will allocate N \n");
int n=0;
if (write(sock, "hi", 2) < 0) { //Send number of bytes
perror("error writing to socket\n");
}
if (read(sock, &n, sizeof(unsigned int)) < 0) {
perror("Error reading from socket\n");
exit(1);
}
int N = ntohl(n);
printf("len is %d\n", N);
char* data = calloc(N, sizeof(char));
int len = read(sock, data, N);
printf("data is %s\n", data);
if (len < 0) {
perror("Error reading from socket\n");
exit(1);
}
for (int i = 0; i < len; i++) {
int tmp = 0;
sprintf(data[i], "%d", tmp);
if (tmp >= 32 & tmp <= 126) {
count++;
__sync_fetch_and_add(&pcc_total[tmp], 1);
}
}
char scount[100];
atoi(count);
write(sock, count, strlen(scount));
free(data);
pthread_exit(NULL);
close(sock);
exit(0);
}
int main(int argc, char *argv[]) {
unsigned int port = atoi(argv[1]);
signal(SIGINT, intHandler);
int socket_desc, client_sock, c, *new_sock;
struct sockaddr_in server, client;
c = sizeof(struct sockaddr_in);
socket_desc = socket( AF_INET, SOCK_STREAM, 0);
if (socket_desc == -1) {
perror("Could not create socket");
exit(1);
}
printf("socket created\n");
memset(&server, 0, c);
server.sin_family = AF_INET;
server.sin_addr.s_addr = htonl(INADDR_ANY);
server.sin_port = htons(port);
if (0 != bind(socket_desc, (struct sockaddr*) &server, sizeof(server))) {
perror("\n Error : Bind Failed \n");
exit(1);
}
printf("bind created\n");
if (0 != listen(socket_desc, 10)) {
perror("\n Error : Listen Failed \n");
exit(1);
}
printf("listen created\n");
while (keepRunning) {
client_sock = accept(socket_desc, (struct sockaddr *) &client,
(socklen_t*) &c);
if (client_sock < 0) {
perror("\n Error : Accept Failed\n");
exit(1);
}
printf("accept created\n");
pthread_t tid;
new_sock = malloc(100*sizeof(int));
*new_sock = client_sock;
if ((pthread_create(&tid, NULL, compute, (void*) new_sock)) < 0) {
perror("could not create thread\n");
exit(1);
}
printf("thread created\n");
// close socket
close(client_sock);
free(new_sock);
pthread_join(tid, NULL);
}
exit(0);
}
I run the code with the following commands:
gcc -std=c99 -O3 -Wall -o pcc_server pcc_server.c -pthread
gcc -std=gnu99 -O3 -Wall -o pcc_client pcc_client.c
There are a number of problems with your code.
On the client side:
When calling fread(), you need to use "rb" instead of "r".
when calling printf() to output the file data that was actually read, you are not null-terminating buffer, or passing its length to printf(). You need to do so.
You are assigning the return value of htonl() to an int instead of an unsigned int.
when calling write() to send the buffer, you are using sizeof(buffer) when you should be using length or N instead (and why are you using two separate variables to hold the same command-line parameter value?). buffer is a pointer to memory allocated with malloc(), so sizeof(buffer) is the same as sizeof(void*), which is not what you want. Also, you are not even calling write() correctly, because your parenthesis are all wrong (they are correct on the previous write() call when sending convertedNum).
likewise, when calling read() to read the recvBuf, you are using sizeof(recvBuf) when you should be using 10 instead, sicne recvBuf is also a pointer to malloced memory.
you are not reading the "hi" greeting that the server sends to the client upon connection, so you lump in those bytes with the bytes of the following size value of the next message, and thus end up with a corrupted C value.
On the server side:
your compute thread routine sends a "hi" greeting to the client, but it does not use any kind of delimiter, like prefixing the greeting with its length, or terminating it with a line break or null character or other unique character, to separate it from any subsequent data. You should always delimit your messages in some manner.
you are closing the accepted socket and freeing the malloced new_sock as soon as you create a worker thread to handle that client. You are ripping away memory from behind the thread's proverbial back. The thread needs to be the one to close the socket and free the memory when it is done using them, not the accept loop.
The thread does attempt to close the socket (but not free the memory), but after it calls pthread_exit() first, which is wrong. pthread_exit() terminates the calling thread, so it needs to be the last thing that the thread calls (DO NOT call exit()!). In fact, don't even call pthread_exit() directly at all, just return from compute(), the pthreads library will then call pthread_exit() for you, passing it whatever void* value you choose to return.
your accept loop should not be calling pthread_join() at all. It blocks the calling thread until the specified thread terminates. That defeats the whole purpose of using threads to handle your clients, and prevents your server from accepting more than 1 client at a time. If you are going to use pthread_join() at all, it should be after the accept loop has ended, so you can wait for any worker threads that may still be running before exiting the app. But that also means keeping track of the pthread_t values that pthread_create() returns, which is more work.
With that said, try this code instead:
Client code:
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <assert.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <dirent.h>
#define FILE_ADDR "/dev/urandom"
char* readMsg(int sockfd, size_t *msgSize)
{
*msgSize = 0;
unsigned int length = 0;
int bytes_read = read(sockfd, &length, sizeof(length)); //Receive number of bytes
if (bytes_read <= 0) {
perror("Error in receiving message from server\n");
return NULL;
}
length = ntohl(length);
char *buffer = malloc(length+1);
if (!buffer) {
perror("Error in allocating memory to receive message from server\n");
return NULL;
}
char *pbuf = buffer;
unsigned int buflen = length;
while (buflen > 0) {
bytes_read = read(sockfd, pbuf, buflen); // Receive bytes
if (bytes_read <= 0) {
perror("Error in receiving message from server\n");
free(buffer);
return NULL;
}
pbuf += bytes_read;
buflen -= bytes_read;
}
*msgSize = length;
return buffer;
}
int sendMsg(int sockfd, char *msg, size_t msgSize)
{
unsigned int convertedNum = htonl(msgSize);
if (write(sockfd, &convertedNum, sizeof(convertedNum)) < 0) { //Send number of bytes
perror("error writing to socket");
return -1;
}
if (write(sockfd, msg, msgSize) < 0) { //Send bytes
perror("error writing to socket");
return -1;
}
return 0;
}
int main(int argc, char *argv[]) {
char* ptr;
//Get command line arguments
unsigned int port = atoi(argv[2]);
unsigned int length = strtoul(argv[3], &ptr, 10); //Number of bytes to read
char* buffer = malloc(length); //Buffer to hold data read from file
struct addrinfo hints, *servinfo, *p;
struct sockaddr_in serv_addr;
int sockfd = -1;
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
int rv = getaddrinfo(argv[1], argv[2], &hints, &servinfo);
if (rv != 0) {
perror("getaddrinfo error\n");
return 1;
}
for (p = servinfo; p != NULL; p = p->ai_next) {
//Initialize socket
sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
if (sockfd < 0)
continue;
//Initialize connection
rv = connect(sockfd, p->ai_addr, (socklen_t) p->ai_addrlen);
if (rv == 0)
break;
close(sockfd);
sockfd = -1;
}
freeaddrinfo(servinfo);
if (sockfd == -1) {
perror("socket create/connect error\n");
return 1;
}
size_t msgSize;
char *msg = readMsg(sockfd, &msgSize);
if (!msg) {
close(sockfd);
return 1;
}
printf("%.*s\n", (int)msgSize, msg);
free(msg);
//Open file for reading
FILE *fp = fopen(FILE_ADDR, "rb");
if (fp == NULL) {
perror("Error in file open\n");
close(sockfd);
return 1;
}
printf("file opened\n");
if (fread(buffer, 1, length, fp) != length) {
perror("Error reading from file\n");
fclose(fp);
close(sockfd);
return 1;
}
fclose(fp);
printf("Buffer is %.*s\n", (int)length, buffer);
if (sendMsg(sockfd, buffer, length) != 0) {
free(buffer);
close(sockfd);
return 1;
}
free(buffer);
printf("send is done \n");
msg = readMsg(sockfd, &msgSize); // response from server
if (!msg) {
close(sockfd);
return 1;
}
printf("# of printable characters: %.*s\n", (int)msgSize, msg);
free(msg);
return 0;
}
Server code:
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <assert.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <dirent.h>
#include <pthread.h>
#include <signal.h>
static volatile int keepRunning = 1;
int pcc_total[159];
void intHandler(int dummy) {
keepRunning = 0;
}
char* readMsg(int sockfd, size_t *msgSize)
{
*msgSize = 0;
unsigned int length = 0;
int bytes_read = read(sockfd, &length, sizeof(length)); //Receive number of bytes
if (bytes_read <= 0) {
perror("Error in receiving message from server\n");
return NULL;
}
length = ntohl(length);
char *buffer = malloc(length+1);
if (!buffer) {
perror("Error in allocating memory to receive message from server\n");
return NULL;
}
char *pbuf = buffer;
unsigned int buflen = length;
while (buflen > 0) {
bytes_read = read(sockfd, pbuf, buflen); // Receive bytes
if (bytes_read <= 0) {
perror("Error in receiving message from server\n");
free(buffer);
return NULL;
}
pbuf += bytes_read;
buflen -= bytes_read;
}
*msgSize = length;
return buffer;
}
int sendMsg(int sockfd, char *msg, size_t msgSize)
{
unsigned int convertedNum = htonl(msgSize);
if (write(sockfd, &convertedNum, sizeof(convertedNum)) < 0) { //Send number of bytes
perror("error writing to socket");
return -1;
}
if (write(sockfd, msg, msgSize) < 0) { //Send bytes
perror("error writing to socket");
return -1;
}
return 0;
}
void *compute(void *socket_desc) {
int sock = * (int*) socket_desc;
free(socket_desc);
if (sendMsg(sock, "hi", 2) != 0) {
perror("error writing to socket\n");
close(sock);
return NULL;
}
size_t length = 0;
char *data = readMsg(sock, &length);
if (!msg) {
close(sock);
return NULL;
}
printf("len is %d\n", (int)length);
printf("data is %.*s\n", (int)length, data);
int count = 0;
for (size_t i = 0; i < length; i++) {
// ...
}
free(data);
char scount[20];
sprintf(scount, "%d", count);
sendMsg(sock, scount, strlen(scount));
close(sock);
return NULL;
}
int main(int argc, char *argv[]) {
unsigned int port = atoi(argv[1]);
signal(SIGINT, intHandler);
int socket_desc, client_sock, c, *new_sock;
struct sockaddr_in server, client;
socket_desc = socket( AF_INET, SOCK_STREAM, 0);
if (socket_desc == -1) {
perror("Could not create server socket");
return 1;
}
printf("server socket created\n");
memset(&server, 0, c);
server.sin_family = AF_INET;
server.sin_addr.s_addr = htonl(INADDR_ANY);
server.sin_port = htons(port);
if (bind(socket_desc, (struct sockaddr*) &server, sizeof(server)) < 0) {
perror("\n Error : Bind Failed \n");
close(socket_desc);
return 1;
}
printf("bind created\n");
if (listen(socket_desc, 10) < 0) {
perror("\n Error : Listen Failed \n");
close(socket_desc);
return 1;
}
printf("listening\n");
while (keepRunning) {
c = sizeof(client);
client_sock = accept(socket_desc, (struct sockaddr *) &client,
(socklen_t*) &c);
if (client_sock < 0) {
perror("\n Error : Accept Failed\n");
continue;
}
printf("client accepted\n");
new_sock = malloc(sizeof(int));
if (!new_sock) {
perror("\n Error : Malloc Failed\n");
close(client_sock);
continue;
}
*new_sock = client_sock;
pthread_t tid;
if (pthread_create(&tid, NULL, &compute, new_sock) != 0) {
perror("\n Error : Thread Create Failed\n");
free(new_sock);
close(client_sock);
continue;
}
printf("thread created\n");
}
close(socket_desc);
return 0;
}
I think you should remove the two lines
close(client_sock);
free(new_sock);
in the server code because the newly created thread can't perform on those variables and memory area if it is freed up at such an early point. Can you try the code again without it?
Your server closes the connected socket and frees the memory in which you stored its file handle immediately after launching the thread to handle that connection. You're unlucky that the server only hangs as a result, but you have data races, so formally your program's behavior is undefined.
Since the server isn't going to do anything else until the thread has finished, you might as well move the close() and free() after the pthread_join(). Or, considering that you do join before creating any other threads, how about just calling compute() synchronously instead of creating a new thread for it to run in?
I just implemented a HTTP/1.1 client to parse the chunked transferring coding. However, it works for some websites but fails for others. I assume I need to read chunkSize + 2 bytes including \r\n for each chunk data, am I right?
Here is my code:
while(chunked)//if detecting chunked in the header before, this is true
{
//getLine is a function can read a line separated by \r\n
//sockfd is a socket created before and file position is at the start of HTTP body (after that blank line between header and body)
line = getLine(sockfd);
printf("%s", line);//print the chunk size line in hex
int chunkSize = strtol(line, NULL, 16);
if(chunkSize == 0)
{
printf("##### Read chunk size of 0, reading until we hit end of stream.\n");
break;
}
printf("##### Chunk size (in hex above) is %d in decimal and is printed here:\n", chunkSize);
char* chunkBuf = (char *)malloc(chunkSize + 2 + 1);//2 for \r\n, 1 for \0
bzero(chunkBuf, chunkSize + 3);
if(read(sockfd, chunkBuf, chunkSize + 2) == 0)//sockfd is a socket created before
{
perror("Read Error: ");
exit(EXIT_FAILURE);
}
printf("%s", chunkBuf);//print the chunk content
free(chunkBuf);
}
Actually I can print out the whole content without parsing, i.e. print line by line, so I think I may make some mistakes in the code above, could anyone give me some hint?
Below is the whole code for your reference:
#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <netdb.h>
#include <netinet/in.h>
#include <string.h>
#include <stdbool.h>
#include <unistd.h>
#define HTTP_VERSION "HTTP/1.1"
#define PAGE "/"
int createSokect()
{
int socketfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(socketfd < 0)
{
perror("Cannot create socket\n");
exit(EXIT_FAILURE);
}
return socketfd;
}
char* getIP(char* host)
{
struct hostent* hent;
int len = 15;//xxx.xxx.xxx.xxx
char *ipaddr = (char *)malloc(len + 1);//one more \0
bzero(ipaddr, len + 1);
if((hent = gethostbyname(host)) == NULL)
{
printf("Cannot get IP for this host: %s\n", host);
exit(EXIT_FAILURE);
}
if(inet_ntop(AF_INET, (void*)hent->h_addr_list[0], ipaddr, len) == NULL)
{
printf("Cannot resolve IP for this host: %s\n", host);
exit(EXIT_FAILURE);
}
return ipaddr;
}
char* createQuery(char* host, char* page)
{
char* msg = "GET %s %s\r\nHost: %s\r\nConnection: close\r\n\r\n";
char* query = (char *)malloc(strlen(host) + strlen(page) + strlen(msg) + strlen(HTTP_VERSION) - 6 + 1);//-6: %s %s %s
sprintf(query, msg, page, HTTP_VERSION, host);
return query;
}
char* getLine(int fd)
{
char c = 0, pre = 0;
char* line = 0;
int size = 1;
int pos = 0;
while(read(fd, &c, 1)!=0)
{
if(pos + 1 == size)
{
size *= 2;
line = realloc(line, size);
}
line[pos++] = c;
//printf("%c", c);
if(pre == '\r' && c == '\n')//this is a new line
{
break;
}
pre = c;
}
if(line)
{
line[pos++] = 0;
}
return line;
}
int main(int argc, char** argv)
{
if(argc < 3)
{
perror("Need more arguments");
exit(EXIT_FAILURE);
}
int sockfd = createSokect();
char* ip = getIP(argv[1]);
printf("Host: %s\n", argv[1]);
printf("IP: %s\n", ip);
struct sockaddr_in server;
server.sin_family = AF_INET;
int err = inet_pton(server.sin_family, ip, (void *)(&(server.sin_addr.s_addr)));
if(err != 1)
{
perror("Cannot convert IP to binary address\n");
exit(EXIT_FAILURE);
}
server.sin_port = htons(atoi(argv[2]));
printf("port: %d\n", server.sin_port);
//connect to the server
if(connect(sockfd, (struct sockaddr *)&server, sizeof(server)) < 0)
{
printf("Cannot connect: %d\n", err);
exit(EXIT_FAILURE);
}
char* query = createQuery(argv[1], PAGE);
printf("##### CLIENT IS SENDING THE FOLLOWING TO SERVER:\n");
printf("%s", query);
int offset = 0;
//send query to the server
err = send(sockfd, query + offset, strlen(query) - offset, 0);
if(err < 0)
{
perror("Cannot send query");
exit(EXIT_FAILURE);
}
printf("##### CLIENT RECEIVED THE FOLLOWING FROM SERVER:\n");
//receive message line by line
bool chunked = false;
char* line;
while((line = getLine(sockfd)) != NULL)
{
printf("%s", line);
if(!strcasecmp(line, "transfer-encoding: chunked\r\n"))
{
chunked = true;
//printf("Chunked here\n");
}
if(!strcmp(line, "\r\n"))
{
printf("##### Just read blank line, now reading body.\n");
if(chunked)//chunked, we print those in another way, otherwise line by line
{
free(line);
break;
}
}
free(line);
}
while(chunked)
{
line = getLine(sockfd);
printf("%s", line);
int chunkSize = strtol(line, NULL, 16);
if(chunkSize == 0)
{
printf("##### Read chunk size of 0, reading until we hit end of stream.\n");
break;
}
printf("##### Chunk size (in hex above) is %d in decimal and is printed here:\n", chunkSize);
char* chunkBuf = (char *)malloc(chunkSize + 2 + 1);//2 for \r\n, 1 for \0
bzero(chunkBuf, chunkSize + 3);
if(read(sockfd, chunkBuf, chunkSize + 2) == 0)
{
perror("Read Error: ");
exit(EXIT_FAILURE);
}
printf("%s", chunkBuf);
free(chunkBuf);
}
//receive message from the server
/*
char buf[2048];
bzero(buf, sizeof(buf));
err = recv(sockfd, buf, sizeof(buf), 0);
if(err < 0)
{
perror("Receive error");
exit(EXIT_FAILURE);
}
char *content = buf;
fprintf(stdout, content);*/
free(query);
free(ip);
close(sockfd);
printf("##### Connection closed by server.\n");
exit(EXIT_SUCCESS);
}
The line:
if(read(sockfd, chunkBuf, chunkSize + 2) == 0) ...
will read up to chunkSize+2, i.e. it can read less. See the manual page of read. Your code shall look something like:
int n = 0;
while (n<chunkSize) {
r = read(sockfd, chunkBuf+n, chunkSize - n);
if (r <= 0) { error or closed conection ... }
n += r;
}
Since I know the chunk size, so I read character one by one counting up to the chunk size. This way can work. But I still don't understand why I failed when trying to use read or recv by the whole chunk size at one time.
I'm playing around with C although I am fairly new to it. to find out how threads and locks work, connections work, within an IRC.
However I have come across and error, and I'm not sure how to fix it.
Bellow are the errors I get.
sample.c: In function ‘clientThreadEntry’:
sample.c:343:5: warning: passing argument 1 of ‘connectionMain’ makes pointer from integer without a cast [enabled by default]
connectionMain(t->sock);
^
sample.c:216:5: note: expected ‘struct client_thread *’ but argument is of type ‘int’
int connectionMain(struct client_thread *t) {
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <string.h>
#include <strings.h>
#include <signal.h>
#include <netdb.h>
#include <time.h>
#include <errno.h>
#include <pthread.h>
#include <ctype.h>
struct client_thread {
pthread_t thread;
int thread_id;
int sock;
char nickname[32];
int state;
#define DEAD 1
#define ALIVE 2
int user_command_seen;
int user_has_registered;
time_t timeout;
char line[1024];
int line_len;
int next_message;
};
/**
Allocate static structure for all client connections.
*/
#define MAX_CLIENTS 50
struct client_thread threads[MAX_CLIENTS];
/**
Number of connections we have open right now.
*/
int clientCount = 0;
pthread_rwlock_t message_log_lock = PTHREAD_RWLOCK_INITIALIZER;
#define MAX_MESSAGES 10000
char messageLogRecipients[MAX_MESSAGES];
char *messageLog[MAX_MESSAGES];
int messageCount = 0;
int messageAppend(char *recipient, char *message) {
/*
If used up all message space, exit.
*/
if (messageCount >= MAX_MESSAGES) return -1;
// Append message.
pthread_rwlock_wrlock(&message_log_lock);
messageLogRecipients[messageCount] = strdup(recipient);
message[messageCount] = strdup(message);
messageCount++;
pthread_rwlock_unlock(&message_log_lock);
return 0;
}
int messageRead(struct client_thread *t) {
pthread_rwlock_rdlock(&message_log_lock);
int i;
for (i = t->next_message + 1; i < messageCount; i++) {
}
t -> next_message = messageCount;
pthread_rwlock_unlock(&message_log_lock);
return 0;
}
int create_listen_socket(int port) {
int sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock == -1) return -1;
int on = 1;
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *) &on, sizeof (on)) == -1) {
close(sock);
return -1;
}
if (ioctl(sock, FIONBIO, (char *) &on) == -1) {
close(sock);
return -1;
}
/* Bind it to the next port we want to try. */
struct sockaddr_in address;
bzero((char *) &address, sizeof (address));
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(port);
if (bind(sock, (struct sockaddr *) &address, sizeof (address)) == -1) {
close(sock);
return -1;
}
if (listen(sock, 20) != -1) return sock;
close(sock);
return -1;
}
int accept_incoming(int sock) {
struct sockaddr addr;
unsigned int addr_len = sizeof addr;
int asock;
if ((asock = accept(sock, &addr, &addr_len)) != -1) {
return asock;
}
return -1;
}
int read_from_socket(int sock, unsigned char *buffer, int *count, int buffer_size,
int timeout) {
fcntl(sock, F_SETFL, fcntl(sock, F_GETFL, NULL) | O_NONBLOCK);
int t = time(0) + timeout;
if (*count >= buffer_size) return 0;
int r = read(sock, &buffer[*count], buffer_size - *count);
while (r != 0) {
if (r > 0) {
(*count) += r;
break;
}
r = read(sock, &buffer[*count], buffer_size - *count);
if (r == -1 && errno != EAGAIN) {
perror("read() returned error. Stopping reading from socket.");
return -1;
} else usleep(100000);
// timeout after a few seconds of nothing
if (time(0) >= t) break;
}
buffer[*count] = 0;
return 0;
}
/**
Function to check is a user has registered yet or not.
*/
int registrationCheck(struct client_thread *t) {
if (t->user_has_registered)
return -1;
if (t->user_command_seen && t->nickname[0]) {
// User has met registration requirements.
t->user_has_registered = 1;
t->timeout = 60;
char msg[8192];
snprintf(msg, 1024, ":myircServer.com 001 %s : You have registered.\n", t->nickname);
write(t->sock, msg, strlen(msg));
snprintf(msg, 1024, ":myircServer.com 002 %s : You have registered.\n", t->nickname);
write(t->sock, msg, strlen(msg));
snprintf(msg, 1024, ":myircServer.com 003 %s : You have registered.\n", t->nickname);
write(t->sock, msg, strlen(msg));
snprintf(msg, 1024, ":myircServer.com 004 %s : You have registered.\n", t->nickname);
write(t->sock, msg, strlen(msg));
snprintf(msg, 1024, ":myircServer.com 253 %s : Unknown connections\n", t->nickname);
write(t->sock, msg, strlen(msg));
snprintf(msg, 1024, ":myircServer.com 254 %s : Channels formed\n", t->nickname);
write(t->sock, msg, strlen(msg));
snprintf(msg, 1024, ":myircServer.com 255 %s : I have ??? clients and ??? servers.\n", t->nickname);
write(t->sock, msg, strlen(msg));
return 0;
}
return -1;
}
int connectionMain(struct client_thread *t) {
int sock = t->sock;
char nickname[8192];
char msg[1024];
snprintf(msg, 1024, ":myircserver.com 020 * :Greetings, from the IRC server\n");
write(sock, msg, strlen(msg));
unsigned char buffer[8192];
int length = 0;
t->timeout = 5;
int timeOfLastData = time(0);
while (1) {
length = 0;
messageRead(t);
read_from_socket(sock, buffer, &length, 8192, 1);
if (length > 0)
{
timeOfLastData = time(0);
}
if (length == 0 && ((time(0) - timeOfLastData) >= t->timeout)) {
snprintf(msg, 1024, "ERROR :Closing Link: Connection timed out.. See ya!\n");
write(sock, msg, strlen(msg));
close(sock);
return 0;
}
buffer[length] = 0;
char channel[8192];
int r = sscanf((char *) buffer, "JOIN %s", channel);
if (r == 1) {
if (!t->user_has_registered) {
snprintf(msg, 1024, ":myircserver.com 241 * :JOIN command sent before registration\n");
write(sock, msg, strlen(msg));
}
}
r = sscanf((char *) buffer, "NICK %s", nickname);
if (r == 1) {
/**
check and saw a nickname from the client.
Need to handle what to do next.
Checks if the nickname provided is less than 1 or greater than 30.
if it is, then send and error since it is invalid and we cannot deal with nicknames of these sizes.
if this isn't in place we would be trying to pass a string to big or too small to our nickname variable.
*/
if (strlen(nickname) > 30 || strlen(nickname) < 1) {
snprintf(msg, 1024, "ERROR :Inviliad nickname: Nickname too short or too long.\n");
write(sock, msg, strlen(msg));
} else {
/**
Nickname is a valid length!
copy nickname to thread variable nickname.
*/
strcpy(t->nickname, nickname);
registrationCheck(t);
}
}
/**
Saw USER command if a NICK has been provided. Then mark connection.
As registered. and send client greeting messages.
If this isnt here, then we will not beable to handle USER command or the like.
*/
if (!strncasecmp("USER ", (char *) buffer, 5)) {
if (t->nickname) {
/**
Nickname has been provided and user has been registered.
*/
t->user_command_seen = 1;
registrationCheck(t);
}
}
/**
Checks if the messaged parsed is correct.
Checks nickname, length and the response are correct and send the correct respose code.
Checks of the PRIVMSG has at least 10 bytes of data to be used.
Needed to see if there is data, and if it is sent before registration.
*/
if (!strncasecmp("PRIVMSG", (char *) buffer, 7)) {
if (!t->user_has_registered){
snprintf(msg, 1024, ":myircserver.com 241 * :PRIVMSG command sent before registration\n");
write(sock, msg, strlen(msg));
} else {
// Client is registered, so handle the message.
char recipient[1024];
char message [1024];
if (sscanf((char *) buffer, "PRIVMSG %s :%[^\n]", recipient, message) == 2){
messageAppend(recipient, message);
} else {
// msg is wrongly formed, error.
snprintf(msg, 1024, ":myircserver.com 461 %s :Wrongly formed PRIVMSG command sent.\n", t->nickname);
write(sock, msg, strlen(msg));
}
}
}
/**
* Client left, we must check and close this or we will get a SIGPIPE error that will kill program.
* Send an error statement back to user so they know what is going on.
*/
if (!strncasecmp("QUIT", (char *) buffer, 4)) {
snprintf(msg, 1024, "ERROR :Closing Link: Connection timed out (see ya!)\n");
write(sock, msg, strlen(msg));
close(sock);
return 0;
}}
close(sock);
return 0;
}
void *clientThreadEntry(void *arg) {
struct client_thread *t = arg;
/**
Run the threads connection handling code through threads.
*/
connectionMain(t->sock);
t->state = DEAD;
return NULL;
}
int handleConnection(int sock) {
printf("WE GET HERE\n");
int i;
for (i = 0; i < clientCount; i++) {
if (threads[i].state == DEAD) {
break;
}}
if (i > MAX_CLIENTS) {
close(sock);
return 1;
}
// clear out client structure, set up for threads.
bzero(&threads[i], sizeof (struct client_thread));
// store file descriptor into thread array.
threads[i].sock = sock;
threads[i].state = ALIVE;
threads[i].thread_id = i;
if (pthread_create(&threads[i].thread, NULL, clientThreadEntry, &threads[i]))
{
close(sock);
return 1;
}
if (i == clientCount) clientCount++;
return 0;
}
int main(int argc, char **argv) {
signal(SIGPIPE, SIG_IGN);
if (argc != 2) {
fprintf(stderr, "usage: sample <tcp port>\n");
exit(-1);
}
int master_socket = create_listen_socket(atoi(argv[1]));
fcntl(master_socket, F_SETFL, fcntl(master_socket, F_GETFL, NULL)&(~O_NONBLOCK));
while (1) {
int client_sock = accept_incoming(master_socket);
if (client_sock != -1) {
// Got connection -- do something with it.
handleConnection(client_sock);
} else {usleep(10000);}
}
}
You have a compilation warning. Your function connectionMain takes a client_thread pointer:
int connectionMain(struct client_thread *t)
{
But you are calling it with a sock integer:
void *clientThreadEntry(void *arg) {
struct client_thread *t = arg;
/**
Run the threads connection handling code through threads.
*/
connectionMain(t->sock);
t->state = DEAD;
return NULL;
}
Presumably you want to call it like so:
connectionMain(t);
That would at least fix the compilation warning.
I am trying to implement a simple HTTP server with C that
reads a request
checks if it is a GET request
reads the URL from the request
Checks if file is on server and tries to open it
I am using strtok for String tokenizing and I think it messes up the filepath. open and fopen always return error codes and are not able to open any files.
Here is my code:
/*
** parser.c
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define MYPORT 3499 // the port users will be connecting to
#define BACKLOG 10 // how many pending connections queue will hold
#define MAXLEN 1024 //upper limit of the length of the string
int main(void)
{
char input[MAXLEN]; //the line that is read from the client
char * token1; //GET request
char * token2; //filepath
char tmpstring[MAXLEN]; //filesize
int sockfd, new_fd; // listen on sock_fd, new connection on new_fd, file open on file_fd
struct sockaddr_in my_addr; // my address information
struct sockaddr_in their_addr; // connector's address information
int sin_size;
int yes=1;
int n; //the amount of read characters from the client
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("socket");
exit(1);
}
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) {
perror("setsockopt");
exit(1);
}
my_addr.sin_family = AF_INET; // host byte order
my_addr.sin_port = htons(MYPORT); // short, network byte order
my_addr.sin_addr.s_addr = INADDR_ANY; // automatically fill with my IP
memset(&(my_addr.sin_zero), '\0', 8); // zero the rest of the struct
if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1) {
perror("bind");
exit(1);
}
if (listen(sockfd, BACKLOG) == -1) {
perror("listen");
exit(1);
}
while(1) { // main accept() loop
sin_size = sizeof(struct sockaddr_in);
if ((new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size)) == -1) {
perror("accept");
continue;
}
printf("server: got connection from %s\n",inet_ntoa(their_addr.sin_addr));
n = readline(new_fd, input, MAXLEN); //n is the amount of read characters
if (n == -1) {
perror("Unable to read line");
}
//Check if it is a GET message
token1 = strtok(input," ");
if(strcmp(token1, "GET") != 0)
{
send(new_fd, "Bad request\n", 30, 0);
}
else
{
//Retrieve the file path
token2 = strtok(NULL, " ");
if(token2 == NULL)
{
send(new_fd, "File path not specified\n", 23, 0); //Check if filename is empty
}
send(new_fd, token2, strlen(token2), 0); //test
printf("%s", token2);
if(token2[0] == '/') //remove the initial slash
memmove(token2, token2 + 1, strlen(token2));
//char * path = "test.html"; //test line
//char * buff;
//int len = sprintf(buff, "1: %d 2: %d\n", strlen(token1), strlen(token2));
//send(new_fd, buff, len, 0);
//Check if file is on the server
if(open(token2, O_RDONLY) < 0) //Error opening file
{
if(errno == EACCES)
send(new_fd, "Access error\n", 30, 0);
else
send(new_fd, "Not existed\n", 30, 0);
}
else
{
FILE * requested_file = fopen(token2, "r");
if(requested_file == NULL) //
{
send(new_fd, "Error in fopen\n", 30, 0);
}
else
{
send(new_fd, "File found\n", 30, 0); //successful
}
fseek(requested_file, 0, SEEK_END); // move to the end of the file
int end= ftell(requested_file); // get the position of the end of file
int stringlen = sprintf(tmpstring, "file size: %d\n", end);
send(new_fd, tmpstring, stringlen, 0);
}
}
close(new_fd); //close connection
}
return 0;
}
//helper function for recieving text
int readline(int fd, char *buf, int maxlen)
{
int n, rc;
char c;
for (n = 1; n < maxlen; n++) {
if ((rc = read(fd, &c, 1)) == 1) {
*buf++ = c;
if (c == '\n')
break;
} else if (rc == 0) {
if (n == 1)
return 0; // EOF, no data read
else
break; // EOF, read some data
} else
return -1; // error
}
*buf = '\0'; // null-terminate
return n;
}
So I'm placing a test.html in the same folder as the server. Then im telnetting to localhost and port 3499. This is the output when entering GET /test.html:
/test.html
Not existed
rError in fopen
Connection closed by foreign host.
try opening "test.html" instead of "\test.html"