Second recv call doesn't receive data, halts the execution in C - c

This is my client program that requests files from the server:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#define SERVER_PORT 5959
#define MAX_LINE 512
void setstring(char *str){
str[MAX_LINE-1]='\0';
}
int main(int argc, char * argv[]){
FILE *fp;
struct hostent *hp;
struct sockaddr_in sin;
char *host;
char filename[MAX_LINE],buf[MAX_LINE],reply[MAX_LINE],rec_line[MAX_LINE];
int s;
char msg[MAX_LINE];
int len,new_len,rec_file;
if (argc==2) {
host = argv[1];
}
else {
fprintf(stderr, "usage: simplex-talk host\n");
exit(1);
}
/* translate host name into peer's IP address */
hp = gethostbyname(host);
if (!hp) {
fprintf(stderr, "simplex-talk: unknown host: %s\n", host);
exit(1);
}
else
printf("Client's remote host: %s\n", argv[1]);
/* build address data structure */
bzero((char *)&sin, sizeof(sin));
sin.sin_family = AF_INET;
bcopy(hp->h_addr, (char *)&sin.sin_addr, hp->h_length);
sin.sin_port = htons(SERVER_PORT);
/* active open */
if ((s = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
perror("simplex-talk: socket");
exit(1);
}
else
printf("Client created socket.\n");
int send_file_name,rec_msg;
if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0)
{
perror("simplex-talk: connect");
close(s);
exit(1);
}
else{
printf("Client connected.\n");
/* main loop: get and send lines of text */
printf("Hello from server\n");
while(!(strcmp(reply,"bye")==0)){
printf("Enter the file name:\n");
scanf("%s",filename);
setstring(filename);
send_file_name=send(s,filename,strlen(filename)+1,0);
if(send_file_name<0)
fputs("Error sending filename",stdout);
rec_msg=recv(s,msg,sizeof(msg),0);
if(strcmp(msg,"File not found")==0)
printf("File not found\n");
else{
printf("%s\n",msg);
fp=fopen(filename,"w");
printf("CP1\n");
if(rec_file=recv(s,rec_line,sizeof(rec_line),0)>0){
printf("CP2");
printf("String recieved:%s\n",rec_line);
if(len=fwrite(rec_line,1,rec_file+1,fp)>0)
printf("Recieved file\n");
else
printf("Error writing to file\n");
}
else
printf("Not recieved\n");
}
printf("Enter 'bye' to terminate requesting files\n");
scanf("%s",reply);
}
}
return 0;
}
This is my server program that accepts request for files from the client:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#define SERVER_PORT 5959
#define MAX_PENDING 5
#define MAX_LINE 256
void setstring(char* str){
str[MAX_LINE-1]='\0';
}
int main(){
FILE *fp;
struct sockaddr_in sin;
char buf[MAX_LINE],msg[MAX_LINE],*rec_line;
int len;
int s, new_s,count;
char str[INET_ADDRSTRLEN];
int error_file,send_msg,read_line,send_file;
bzero((char *)&sin, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = inet_addr("0.0.0.0");
sin.sin_port = htons(SERVER_PORT);
/* setup passive open */
if ((s = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
perror("simplex-talk: socket");
exit(1);
}
inet_ntop(AF_INET, &(sin.sin_addr), str, INET_ADDRSTRLEN);
printf("Server is using address %s and port %d.\n", str, SERVER_PORT);
if ((bind(s, (struct sockaddr *)&sin, sizeof(sin))) < 0) {
perror("simplex-talk: bind");
exit(1);
}
else
printf("Server bind done.\n");
listen(s, MAX_PENDING);
/* wait for connection, then receive and print text */
while(1) {
if ((new_s = accept(s, (struct sockaddr *)&sin, &len)) < 0) {
perror("simplex-talk: accept");
exit(1);
}
printf("Server Listening.\n");
printf("Greetings\n");
int rec_file_name=recv(new_s,buf,sizeof(buf),0);
if(rec_file_name>0)
printf("File requested:%s\n",buf);
fp=fopen(buf,"r");
if(fp==NULL)
{
fputs("File not found\n",stdout);
strcpy(buf,"File not found");
if(error_file=send(new_s,buf,strlen(buf)+1,0)>0)
fputs("Successfully send error message to client\n",stdout);
}
else{
bzero(buf,MAX_LINE);
printf("File found :) \n");
strcpy(buf,"OK");
if(send_msg=send(new_s,buf,strlen(buf)+1,0)>0)
fputs("File found message sent to client\n",stdout);
fseek(fp,0,SEEK_END);
int file_size=ftell(fp);
fseek(fp,0,SEEK_SET);
printf("File size:%d\n",file_size);
rec_line=(char *)malloc(sizeof(char)*(file_size));
read_line=fread(rec_line,1,file_size+1,fp);
printf("File read: %s\n",rec_line);
if(send_file=send(new_s,rec_line,strlen(rec_line)+1,0)>0)
printf("File string sent to client\n");
}
}
close(new_s);
}
The problem is that in the client, my second recv() call, where it is supposed to receive the contents of a file, shows nothing. The programs halts at that point, but the server programs displays that it has sent the file contents. The client doesn't receive it.

The basic problem is that you're not checking the return values to see how much data you actually sent and received. So when the client calls:
rec_msg=recv(s,msg,sizeof(msg),0);
it will receive up to sizeof(msg) (512) bytes, which is probably both the OK message the server is sending AND the file contents (after the NUL). Which means when it does a second recv call to get the contents, it blocks, because it already read the contents in the first call and there's no more data waiting in the receive buffer.

Your error-checking is haphazard, and consequently you're certainly missing a problem that occurs before the behavior you're observing. I recommend you follow RW Steven's idiom:
int n;
if( (n = recv(new_s, buf, sizeof(buf), 0)) < 0 ) {
err(EXIT_FAILURE, "recv %d", __LINE__);
}
Test every function call, and handle every error. For simple programs, just call err(3) on error. Do that consistently, and the program's behavior will be much less mysterious (if still occasionally surprising). And don't be afraid of the spacebar! It's easy to hit, and easier still to read.
My other bit of advice, if I may, concerns
int send_file_name,rec_msg;
Names like that are confusing. A name is almost never an integer. For I/O sizes, just use one simple name like n, len, or size. Even if you don't care for yourself, you want to care before publishing your question in an open forum. Otherwise, when people see
send_file_name=send(s,filename,strlen(filename)+1,0);
they may think send is some function other than send(2), or that the person asking the question was careless.

The main problem I see is that neither the client nor the server are handling socket I/O correctly in general. They are not handling the cases where reads and writes transfer fewer bytes then requested, you need to loop the I/O. And the client is reading too many bytes from the server anyway, which is why your second recv() is blocking. And you are relying on a disconnect to indicate the end of the file has been reached, but that does not allow the client to do adequate error checking to know if the full file was actually received or not.
Also, when sending the content of a file, the server is attempting to read the entire file into memory (bad!), not doing adequate error checking on the file I/O, and it is treating the file content as text instead of as binary (don't use strlen() on binary data!).
Try something more like this instead:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#define SERVER_PORT 5959
#define MAX_LINE 512
int sendstring(int sock, const char *str) {
if (!str) str = "";
int len = strlen(str) + 1;
do {
int ret = send(sock, str, len, 0);
if (ret <= 0) return -1;
str += ret;
len -= ret;
}
while (len > 0);
return 0;
}
int readbuf(int sock, void *buf, int buflen) {
char *pbuf = (char*) buf;
while (buflen > 0) {
int len = recv(sock, pbuf, buflen, 0);
if (len <= 0) return -1;
pbuf += len;
buflen -= len;
}
return 0;
}
int readstring(int sock, char *str, int maxlen) {
while (maxlen > 0) {
if (recv(sock, str, 1, 0) <= 0) return -1;
if (*str == '\0') return 0;
++str;
--maxlen;
}
return -2;
}
int readfile(int sock, int fd) {
int filesize;
char buf[MAX_LINE];
if (readbuf(sock, &filesize, sizeof(filesize)) < 0) return -1;
filesize = ntohl(filesize);
while (filesize > 0) {
int len = readbuf(sock, buf, min(sizeof(buf), filesize));
if (len < 0) return -1;
if (fwrite(buf, len, 1, fp) != 1) return -2;
filesize -= len;
}
return 0;
}
int main(int argc, char * argv[]) {
char filename[MAX_LINE], reply[MAX_LINE];
if (argc != 2) {
fprintf(stderr, "usage: simplex-talk host\n");
exit(1);
}
char *host = argv[1];
/* translate host name into peer's IP address */
struct hostent *hp = gethostbyname(host);
if (!hp) {
fprintf(stderr, "simplex-talk: unknown host: %s\n", host);
exit(1);
}
if (hp->h_addrtype != AF_INET) {
fprintf(stderr, "simplex-talk: unsupported address type %d for host: %s\n", hp->h_addrtype, host);
exit(1);
}
/* build address data structure */
struct sockaddr_in sin;
bzero((char *)&sin, sizeof(sin));
sin.sin_family = AF_INET;
bcopy(hp->h_addr, &sin.sin_addr, hp->h_length);
sin.sin_port = htons(SERVER_PORT);
printf("Host's remote IP: %s\n", inet_ntoa(&sin.sin_addr));
/* active open */
int s = socket(PF_INET, SOCK_STREAM, 0);
if (s < 0) {
perror("simplex-talk: socket");
exit(1);
}
printf("Client created socket.\n");
if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0)
{
perror("simplex-talk: connect");
close(s);
exit(1);
}
printf("Client connected.\n");
/* main loop: get and send lines of text */
do {
printf("Enter the file name ('bye' to quit):\n");
if (scanf("%512s", filename) != 1) {
printf("Error reading filename\n");
break;
}
if (strcmp(filename, "bye") == 0) {
sendstring(s, "bye");
break;
}
if (sendstring(s, filename) < 0) {
printf("Error sending filename\n");
break;
}
if (readstring(s, reply, sizeof(reply)) < 0) {
printf("Error reading reply\n");
break;
}
if (strcmp(reply, "OK") != 0) {
printf("%s\n", reply);
if (strcmp(reply, "bye") == 0) break;
continue;
}
FILE *fp = fopen(filename, "wb");
if (!fp) {
printf("Error opening file\n");
break;
}
printf("Receiving file\n");
int ret = readfile(s, fd);
fclose(fp);
if (ret < 0) {
if (ret == -2)
printf("Error writing file\n");
else
printf("Error reading file\n");
break;
}
printf("Received file\n");
}
while (1);
close(s);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#define SERVER_PORT 5959
#define MAX_PENDING 5
#define MAX_LINE 512
int sendbuf(int sock, void *buf, int buflen) {
char *pbuf = (char*) buf;
while (len > 0) {
int len = send(sock, pbuf, buflen, 0);
if (len <= 0) return -1;
pbuf += len;
buflen -= len;
}
return 0;
}
int sendstring(int sock, const char *str) {
if (!str) str = "";
return sendbuf(sock, str, strlen(str) + 1);
}
int sendfile(int sock, int fd) {
char buf[MAX_LINE];
struct stat s;
if (fstat(fd, &s) < 0) return -2;
int pos = ftell(fp);
if (pos == -1) return -2;
int file_size = s.st_size - pos;
int tmp_file_size = htonl(file_size);
if (sendbuf(sock, &tmp_file_size, sizeof(tmp_file_size)) < 0) return -1;
while (file_size > 0) {
int len = fread(buf, 1, min(sizeof(buf), file_size), fp);
if (len < 1) return -2;
if (sendbuf(sock, buf, len) < 0) return -1;
file_size -= len;
}
return 0;
}
int readstring(int sock, char *str, int maxlen) {
while (maxlen > 0) {
if (recv(sock, str, 1, 0) <= 0) return -1;
if (*str == '\0') return 0;
++str;
--maxlen;
}
return -2;
}
int main() {
char msg[MAX_LINE];
struct sockaddr_in sin;
bzero((char *)&sin, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = INADDR_ANY;
sin.sin_port = htons(SERVER_PORT);
/* setup passive open */
int s = socket(PF_INET, SOCK_STREAM, 0);
if (s < 0) {
perror("simplex-talk: socket");
exit(1);
}
printf("Server is using address %s and port %d.\n", inet_ntoa(&(sin.sin_addr)), SERVER_PORT);
if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
perror("simplex-talk: bind");
close(s);
exit(1);
}
printf("Server bind done.\n");
if (listen(s, MAX_PENDING) < 0) {
perror("simplex-talk: listen");
close(s);
exit(1);
}
printf("Server Listening.\n");
/* wait for connection, then receive and print text */
do {
int len = sizeof(sin);
int cli_s = accept(s, (struct sockaddr *)&sin, &len);
if (cli_s < 0) {
perror("simplex-talk: accept");
close(s);
exit(1);
}
printf("Client connected\n");
do {
if (readstring(cli_s, msg, sizeof(msg)) < 0) {
printf("Error reading request\n");
break;
}
if (strcmp(msg, "bye") == 0) break;
printf("File requested: %s\n", msg);
FILE *fp = fopen(msg, "rb");
if (!fp)
{
printf("Cannot open file\n");
if (sendstring(cli_s, "Cannot open file") < 0) {
printf("Error sending reply\n");
break;
}
continue;
}
printf("File found :) \n");
if (sendstring(cli_s, "OK") < 0) {
printf("Error sending reply\n");
fclose(fp);
break;
}
ret = sendfile(cli_s, fp);
fclose(fp);
if (ret < 0) {
printf("Error sending file\n");
break;
}
printf("File sent to client\n");
}
while (1);
close(cli_s);
}
while (1);
close(s);
return 0;
}

Related

Server and client data send() and recv() issue

I have been trying to write a client and server program using C socket programming that does 2 tasks
On prompted from server -> OS command is executed in client machine
Output is stored in a file which is sent back to server. Where server reads it and displays the data plus writes the data in a file on server side.
Issue
When client sends file to the server, server does not display whole data and looks like recv() keeps waiting on socket.
Need some help
Here's the code
server code
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#define SIZE 1024
void write_file(char *filename,int sockfd){
int n;
FILE *fp ;
char buffer[SIZE] ;
fp = fopen(filename, "w");
while (1) {
n = recv(sockfd, buffer, SIZE, 0);
if (n <= 0){
break;
return;
}
printf("%s", buffer) ;
fprintf(fp, "%s", buffer);
bzero(buffer, SIZE);
}
fclose(fp) ;
return;
}
int main(int argc, char *argv[]){
int portno = 7416;
int e,n,n1;
char *cmd ;
int sockfd;
struct sockaddr_in server_addr;
struct hostent *server;
char *fle = "/tmp/reposvr.";
FILE *fp;
char *num ;
if (argc < 3) {
fprintf(stderr,"usage %s hostname command \n", argv[0]);
exit(0);
}
cmd=argv[2] ;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd < 0) {
perror("[-]Error in socket");
exit(1);
}
printf("[+]Server socket created successfully.\n");
server = gethostbyname(argv[1]);
if (server == NULL) {
fprintf(stderr,"ERROR, no such host\n");
exit(0);
}
//server_addr.sin_family = AF_INET;
//server_addr.sin_port = port;
//server_addr.sin_addr.s_addr = inet_addr(ip);
bzero((char *) &server_addr, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(portno);
server_addr.sin_addr = *((struct in_addr *)server->h_addr);
memset(server_addr.sin_zero, '\0', sizeof server_addr.sin_zero);
e = connect(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr));
if(e == -1) {
perror("[-]Error in socket");
exit(1);
}
printf("[+]Connected to Server.\n");
n = write(sockfd, cmd , strlen(cmd));
if (n < 0)
error("ERROR writing to socket");
char *filename=NULL;
filename = (char*)malloc( 50 * sizeof(char) ) ;
strcpy(filename,fle );
n1=rand();
if (asprintf(&num, "%d", n1) == -1) {
perror("asprintf");
} else {
strcat(filename, num);
printf("%s\n", filename);
free(num);
}
printf("%s\n",filename) ;
write_file(filename,sockfd) ;
printf("[+]File data sent successfully.\n");
printf("[+]Closing the connection.\n");
close(sockfd);
return 0;
}
Client code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>
#define SIZE 1024
void send_file(FILE *fp, int sockfd){
int n;
char data[SIZE] = {0};
while(fgets(data, SIZE, fp) != NULL) {
if (send(sockfd, data, sizeof(data), 0) == -1) {
perror("[-]Error in sending file.");
exit(1);
}
bzero(data, SIZE);
}
}
int main(){
int port = 7416;
int e,n1, n ;
FILE *fp ;
char filename[50] = "/tmp/gateway." ;
char command[50];
char *num;
FILE *pf;
char data[SIZE];
int sockfd, new_sock;
struct sockaddr_in server_addr, new_addr;
socklen_t addr_size;
char buffer[SIZE];
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd < 0) {
perror("[-]Error in socket");
exit(1);
}
printf("[+]Server socket created successfully.\n");
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(port);
server_addr.sin_addr.s_addr = INADDR_ANY;
e = bind(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr));
if(e < 0) {
perror("[-]Error in bind");
exit(1);
}
printf("[+]Binding successfull.\n");
if(listen(sockfd, 10) == 0){
printf("[+]Listening....\n");
}else{
perror("[-]Error in listening");
exit(1);
}
addr_size = sizeof(new_addr);
while ( new_sock = accept(sockfd, (struct sockaddr*)&new_addr, &addr_size) )
{
printf("server: got connection from %s port %d\n",
inet_ntoa(new_addr.sin_addr), ntohs(new_addr.sin_port));
n = read(new_sock,buffer,1024);
if (n < 0) error("ERROR reading from socket");
strcpy(command, buffer) ;
printf("%s",command) ;
pf = popen(command,"r");
bzero(data,1024);
n1=rand();
if (asprintf(&num, "%d", n1) == -1) {
perror("asprintf");
} else {
strcat(filename, num);
printf("%s\n", filename);
free(num);
}
printf("%s",filename) ;
fp=fopen(filename,"w" );
while (fgets(data, 2048, pf) != NULL) {
printf("%s", data);
fprintf(fp, "%s",data) ;
}
fclose(fp) ;
fp = fopen(filename, "r");
if (fp == NULL) {
perror("[-]Error in reading file.");
exit(1);
}
send_file(fp, new_sock);
printf("[+]Data written in the file successfully.\n");
}
return 0;
}
Execution output
Edit
Based on the suggestions in this forum, I increased SIZE to 2048 and found that now it returns less rows and hangs after 4-5 rows itself. This is weird. I am sure it's not because of SIZE.
If you see, in client side, we are able to successfully write all in a file. Second part of the program is to read from file and send it to server. Here I am iterating through whole file and sending the data to server. The data send loop is working nicely as I have printf in same loop and we can see all data getting printed.
Looking at server side, here also we are looping till number of bytes read are < 1. Theoretically, this should work. I am sure there's some tiny silly thing that I am missing. Just not able to put my finger on it. Really need some insights in here.
Edit 2
Already tried SIZE , MSG_PEEK as you can see in comments. Any more suggestions ?

openSSL C program

I wrote a program to send the contents of a file between a computer and a raspberry pi 4; on localhost it works but when I try it between the two hosts it does not work.
The output is "Send Success, NumBytes = 7" from the sender part and "Receive Success, NumBytes = 0" from the receiver part.
I created the certificate following this guide: https://www.simba.com/products/SEN/doc/Client-Server_user_guide/content/clientserver/configuringssl/signingca.htm
sender.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <libgen.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include "transfer.h"
#include <openssl/ssl.h>
void sendfile(FILE *fp, SSL *ssl);
ssize_t total = 0;
SSL_CTX *ctx;
int main(int argc, char *argv[])
{
SSL *ssl;
if (argc != 3)
{
perror("usage:send_file filepath <IPaddress>");
exit(1);
}
SSL_library_init();
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
{
perror("Can't allocate sockfd");
exit(1);
}
if ((ctx = SSL_CTX_new(SSLv23_client_method())) == NULL)
{
fprintf(stderr, "ERROR: failed to create SSL_CTX\n");
return -1;
}
SSL_CTX_set_options(ctx,SSL_OP_NO_TLSv1_3);
if (SSL_CTX_load_verify_locations(ctx, "./certs/CA-cert.pem", 0) != 1)
{
fprintf(stderr, "Error loading ./certs/cacert.pem, please check the file.\n");
exit(EXIT_FAILURE);
}
struct sockaddr_in serveraddr;
memset(&serveraddr, 0, sizeof(serveraddr));
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons(SERVERPORT);
if (inet_pton(AF_INET, argv[2], &serveraddr.sin_addr) < 0)
{
perror("IPaddress Convert Error");
exit(1);
}
if (connect(sockfd, (const struct sockaddr *)&serveraddr, sizeof(serveraddr)) < 0)
{
perror("Connect Error");
exit(1);
}
if ((ssl = SSL_new(ctx)) == NULL)
{
fprintf(stderr, "ERROR: failed to create SSL object\n");
return -1;
}
/* Attach SSL to the socket */
SSL_set_fd(ssl, sockfd);
/* Connect to SSL on the server side */
if (SSL_connect(ssl) < 0)
{
fprintf(stderr, "ERROR: failed to connect to SSL\n");
return -1;
}
char *filename = basename(argv[1]);
if (filename == NULL)
{
perror("Can't get filename");
exit(1);
}
char buff[BUFFSIZE] = {0};
strncpy(buff, filename, strlen(filename));
if (send(sockfd, buff, BUFFSIZE, 0) == -1)
{
perror("Can't send filename");
exit(1);
}
FILE *fp = fopen(argv[1], "rb");
if (fp == NULL)
{
perror("Can't open file");
exit(1);
}
sendfile(fp, ssl);
//puts("Send Success");
printf("Send Success, NumBytes = %d\n", total);
fclose(fp);
close(sockfd);
SSL_free(ssl);
SSL_CTX_free(ctx);
return 0;
}
void sendfile(FILE *fp, SSL *ssl)
{
int n;
char sendline[MAX_LINE] = {0};
while ((n = fread(sendline, sizeof(char), MAX_LINE, fp)) > 0)
{
total += n;
if (n != MAX_LINE && ferror(fp))
{
perror("Read File Error");
exit(1);
}
if (SSL_write(ssl, sendline, strlen(sendline)) <= 0)
{
perror("Can't send file\n");
exit(1);
}
memset(sendline, 0, MAX_LINE);
}
}
receiver.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include "transfer.h"
#include <openssl/ssl.h>
void writefile(SSL *ssl, FILE *fp);
ssize_t total = 0;
int main(int argc, char *argv[])
{
SSL_CTX *ctx;
SSL *ssl;
SSL_library_init();
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == -1)
{
perror("Can't allocate sockfd");
exit(1);
}
ctx = SSL_CTX_new(SSLv23_method());
SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv3);
if (ctx == NULL)
{
fprintf(stderr, "ERROR: failed to create SSL_CTX\n");
return -1;
}
if (SSL_CTX_load_verify_locations(ctx, "./certs/CA-cert.pem", 0) != 1)
{
fprintf(stderr, "Error loading ./certs/ca-cert.pem, please check the file.\n");
return -1;
}
if (SSL_CTX_use_certificate_file(ctx, "./certs/server-cert.pem", SSL_FILETYPE_PEM) != 1)
{
fprintf(stderr, "Error loading ./certs/servercert.pem, please check the file.\n");
return -1;
}
if (SSL_CTX_use_PrivateKey_file(ctx, "./certs/server-key.pem", SSL_FILETYPE_PEM) != 1)
{
fprintf(stderr, "Error loading ./certs/serverkey.pem, please check the file.\n");
return -1;
}
//SSL_CTX_set_options(ctx,SSL_OP_NO_TICKET);
struct sockaddr_in clientaddr, serveraddr;
memset(&serveraddr, 0, sizeof(serveraddr));
serveraddr.sin_family = AF_INET;
serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
serveraddr.sin_port = htons(SERVERPORT);
if (bind(sockfd, (const struct sockaddr *)&serveraddr, sizeof(serveraddr)) == -1)
{
perror("Bind Error");
exit(1);
}
if (listen(sockfd, LINSTENPORT) == -1)
{
perror("Listen Error");
exit(1);
}
socklen_t addrlen = sizeof(clientaddr);
int connfd = accept(sockfd, (struct sockaddr *)&clientaddr, &addrlen);
if (connfd == -1)
{
perror("Connect Error");
exit(1);
}
close(sockfd);
if ((ssl = SSL_new(ctx)) == NULL)
{
fprintf(stderr, "ERROR: failed to create SSL object\n");
return -1;
}
SSL_set_fd(ssl, connfd);
/* Establish TLS connection */
int ret = SSL_accept(ssl);
if (ret < 0)
{
fprintf(stderr, "SSL_accept error = %d\n", SSL_get_error(ssl, ret));
return -1;
}
char filename[BUFFSIZE] = {0};
if (recv(connfd, filename, BUFFSIZE, 0) == -1)
{
perror("Can't receive filename");
exit(1);
}
FILE *fp = fopen("output.txt", "wb");
if (fp == NULL)
{
perror("Can't open file");
exit(1);
}
char addr[INET_ADDRSTRLEN];
printf("Start receive file: %s from %s\n", filename, inet_ntop(AF_INET, &clientaddr.sin_addr, addr, INET_ADDRSTRLEN));
writefile(ssl, fp);
printf("Receive Success, NumBytes = %d\n", total);
SSL_free(ssl);
SSL_CTX_free(ctx);
fclose(fp);
close(connfd);
return 0;
}
void writefile(SSL *ssl, FILE *fp)
{
ssize_t n;
char buff[MAX_LINE] = {0};
clock_t t;
t = clock();
while ((n = SSL_read(ssl, buff, sizeof(buff))) > 0)
{
total += n;
if (n == -1)
{
perror("Receive File Error");
exit(1);
}
if (fwrite(buff, sizeof(char), n, fp) != n)
{
perror("Write File Error");
exit(1);
}
memset(buff, 0, MAX_LINE);
}
t = clock() - t;
double time_taken = ((double)t)/CLOCKS_PER_SEC; // in seconds
printf("%f seconds to receive data \n", time_taken);
}
Thanks
The receiver calls recv() on connfd after this file descriptor has been given to the ssl connection, so there is nothing more to be read on the ssl connection.

C TCP client-server segmentation fault problem

I am trying to implement a client-server program in C with TCP for an exercise. The server should be able to serve many clients. The clients asks for some files that the server sends them. Each time the client ends, the server crashes with a segmentation fault error. It prints the "end of service", looking at gdb it also returns to the main function, but it never prints the "prova" after the call to the 'service' function, inside the loop.
Here you can see my server and below my client
/*
* TEMPLATE
*/
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#include <errno.h>
#include <ctype.h>
#include <time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <rpc/xdr.h>
#include <stdint.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include "../errlib.h"
#include "../sockwrap.h"
#define BUFLEN 1024 /* Buffer length */
char *prog_name;
char *err="-ERR\r\n";
void service(int s);
uint32_t getFileCreationTime(char *filename);
int main (int argc, char *argv[])
{
int conn_request_skt; /* passive socket */
uint16_t lport_n, lport_h; /* port used by server (net/host ord.) */
int bklog = 2; /* listen backlog */
int s; /* connected socket */
socklen_t addrlen;
struct sockaddr_in saddr, caddr; /* server and client addresses */
prog_name = argv[0];
if (argc != 2)
{
printf("Usage: %s <port number>\n", prog_name);
exit(1);
}
/* get server port number */
if (sscanf(argv[1], "%" SCNu16, &lport_h)!=1)
err_sys("Invalid port number");
lport_n = htons(lport_h);
/* create the socket */
printf("creating socket...\n");
s = Socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
printf("done, socket number %u\n",s);
/* bind the socket to any local IP address */
bzero(&saddr, sizeof(saddr));
saddr.sin_family = AF_INET;
saddr.sin_port = lport_n;
saddr.sin_addr.s_addr = INADDR_ANY;
showAddr("Binding to address", &saddr);
Bind(s, (struct sockaddr *) &saddr, sizeof(saddr));
printf("done.\n");
/* listen */
printf ("Listening at socket %d with backlog = %d \n",s,bklog);
Listen(s, bklog);
printf("done.\n");
conn_request_skt = s;
/* main server loop */
for (;;)
{
printf("loop again\n");
/* accept next connection */
addrlen = sizeof(struct sockaddr_in);
s = Accept(conn_request_skt, (struct sockaddr *) &caddr, &addrlen);
showAddr("Accepted connection from", &caddr);
printf("new socket: %u\n",s);
/* serve the client on socket s */
service(s);
printf("Prova\n");
}
return 0;
}
uint32_t getFileCreationTime(char *filename)
{
struct stat *attr;
stat(filename, attr);
return attr->st_mtime;
}
void service(int s)
{
char rbuf[BUFLEN+1]; /* reception buffer */
char buf[BUFLEN]; /* sending buffer */
char sbuf[BUFLEN]; /* buffer that will contain the dimension of the file */
int n;
char *get, *filename, filename_stats[20];
size_t len;
uint32_t bsent, dimension, modtime;
FILE *fp;
struct stat * fstatus;
for (;;)
{
n=recv(s, rbuf, BUFLEN-1, 0);
if (n < 0)
{
printf("Read error\n");
close(s);
printf("Socket %d closed\n", s);
break;
}
else if (n==0)
{
printf("Connection closed by party on socket %d\n",s);
close(s);
break;
}
else
{
rbuf[n]=0;
get = strtok(rbuf, " ");
filename = strtok(NULL, "\r\n");
if(strcmp(get, "GET") == 0)
{
printf("\nA client requested the file '%s'\n", filename);
fp = fopen(filename, "rb");
if (fp == NULL)
{
printf("-ERR\tCould not open the file\n");
if(writen(s, err, 6) != 6)
printf("Write error\n");
}
fseek (fp, 0, SEEK_END);
dimension = ftell (fp);
//dimension--;
fseek (fp, 0, SEEK_SET);
sprintf(sbuf, "+OK\r\n");
printf("Sending:\n%s\n", sbuf);
if(writen(s, sbuf, 5) != 5)
printf("Write error\n");
//printf("Sending:\n%d\n", dimension);
//dimension = htonl(dimension);
//printf("dimension net=%d\n", dimension);
if(writen(s, &dimension, 4) != 4)
printf("Write error\n");
//dimension = ntohl(dimension);
printf("dimension=%d\n", dimension);
bsent=0;
while(bsent!=dimension)
{
if(dimension-bsent < BUFLEN)
{
//printf("bytes to send <BUFLEN\n");
fread (buf, 1, dimension-bsent, fp);
printf("Sending last %d bytes of the file\n", dimension-bsent);
if(writen(s, buf, dimension-bsent) != dimension-bsent)
printf("Write error\n");
bsent+=dimension-bsent;
}
else
{
//printf("bytes to send > BUFLEN\n");
fread (buf, 1, BUFLEN, fp);
//printf("Sending:\n%s\n", buf);
if(writen(s, buf, BUFLEN) != BUFLEN)
printf("Write error\n");
bsent+=BUFLEN;
printf("Bytes sent: %d\n", bsent);
}
}
fclose (fp);
modtime = getFileCreationTime(filename);
printf("Sending:\n%d\n", modtime);
//modtime = htonl(modtime);
if(writen(s, &modtime, 4) != 4)
printf("Write error\n");
printf("File '%s' correctly sent to the requesting client\n", filename);
}
else //invalid request
{
printf("-ERR\tINVALID REQUEST\n");
if(writen(s, err, 6) != 6)
printf("Write error\n");
}
}
}
printf("End of service\n");
return;
}
And here's the client:
/*
* TEMPLATE
*/
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#include <errno.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <rpc/xdr.h>
#include <stdint.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include "../errlib.h"
#include "../sockwrap.h"
#define BUFLEN 1024 /* Buffer length */
char *prog_name;
int main (int argc, char *argv[])
{
char buf[BUFLEN]; /* transmission buffer */
char rbuf[BUFLEN]; /* receiving buffer */
char ok[5]; /* buffer used to receive the "+OK" message */
uint16_t tport_n, tport_h; /* server port number (net/host ord) */
char **filenames, *out="_out";
FILE* fp;
size_t len;
int s, result, i;
struct sockaddr_in saddr; /* server address structure */
struct in_addr sIPaddr; /* server IP addr. structure */
ssize_t nreadok, nread;
size_t nleft;
uint32_t breceived , bytes, timestamp;
prog_name = argv[0];
if(argc<4)
{
printf("Error! Usage: %s IP_addr port_number filename1 filename2 filename3 ...\n", prog_name);
return -1;
}
filenames = (char **) malloc(argc*sizeof(char*));
for(i=3; i<argc; i++)
{
filenames[i-3] = (char*) malloc (30*sizeof(char));
strcpy(filenames[i-3], argv[i]);
}
/* input IP address and port of server */
result = inet_aton(argv[1], &sIPaddr);
if (!result)
err_quit("Invalid address");
if (sscanf(argv[2], "%" SCNu16, &tport_h)!=1)
err_quit("Invalid port number");
tport_n = htons(tport_h);
/* create the socket */
printf("Creating socket\n");
s = Socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
printf("done. Socket fd number: %d\n",s);
/* prepare address structure */
bzero(&saddr, sizeof(saddr));
saddr.sin_family = AF_INET;
saddr.sin_port = tport_n;
saddr.sin_addr = sIPaddr;
/* connect */
showAddr("Connecting to target address", &saddr);
Connect(s, (struct sockaddr *) &saddr, sizeof(saddr));
printf("done.\n");
for(i=3; i<argc; i++)
{
//filename=argv[i];
sprintf(buf, "GET %s\r\n", filenames[i-3]); //creating the request "GET filename"
len = strlen(buf);
printf("\n%s", buf);
if(writen(s, buf, len) != len) //sending the request
{
printf("Write error\n");
}
printf("\nwaiting for response...\n");
//filename=argv[i];
//char rbuf[BUFLEN];
nread = readn(s, rbuf, 5); //receiving "+OK\r\n"
if(nread == 0)
printf("Connection closed\n");
if(rbuf[0] == '-')
{
nread = readn(s, rbuf, 1); //remaining byte of the "-ERR\r\n" message
if(nread==0)
printf("Connection closed\n");
printf("-ERROR! The server could not answer the request\n");
close(s);
return -1;
}
bytes=0;
//printf("Bytes 0=%d\n", bytes);
nread = readn(s, &bytes, 4); //receiving the dimension
if(nread == 0)
printf("Connection closed\n");
//printf("Bytes net=%d\n", bytes);
//bytes = ntohl(bytes);
printf("Dimension of the file = %d\n", bytes);
/*
nread = readn(s, rbuf, bytes-1); //receiving the file
if(nread == 0)
printf("Connection closed\n");
*/
strcat(filenames[i-3], "_copy");
fp = fopen(filenames[i-3], "wb"); //creating the file "filename_out"
if (fp == NULL)
{
printf("Could not open the file\n");
}
else
{
//coping data into the copy of the file
breceived=0;
while(1)
{
rbuf[0]=0;
if(bytes-breceived < BUFLEN)
{
//printf("bytes to receive <BUFLEN\n");
printf("Receiving: %d bytes of the file\n", bytes-breceived);
if(readn(s, rbuf, bytes-breceived) != bytes-breceived)
printf("Connection closed\n");
//printf("receiving:\n%s\n", rbuf);
//fputs(rbuf, fp);
fwrite(rbuf, 1, bytes-breceived, fp);
breceived+=bytes-breceived;
printf("Bytes received: %d\n", breceived);
break;
}
else
{
printf("bytes to receive(>BUFLEN) = %d\n", bytes-breceived);
//printf("receiving:\n%s\n", rbuf);
if(readn(s, rbuf, BUFLEN) != BUFLEN)
printf("Connection closed\n");
//printf("receiving:\n%s\n", rbuf);
//fputs(rbuf, fp);
fwrite(rbuf, 1, BUFLEN, fp);
breceived=breceived+BUFLEN;
printf("Bytes received: %d\n", breceived);
}
}
}
if(rbuf[0] == '-')
{
nread = readn(s, rbuf, 1); //remaining byte of the "-ERR\r\n" message
if(nread==0)
printf("Connection closed\n");
printf("-ERROR! The server could not answer the request\n");
close(s);
return -2;
}
//rbuf[bytes]=0;
nread = readn(s, &timestamp, 4); //receiving the timestamp
if(nread == 0)
printf("Connection closed\n");
//timestamp = ntohl(timestamp);
printf("\nFile received: '%s'\t %d bytes \t last mod: %d\n\n", filenames[i-3], bytes, timestamp);
fclose(fp);
}
printf("Closing the connection\n");
close(s);
return 0;
}

Sending to client from server [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 6 years ago.
Improve this question
I'm trying to send data from a server to a client whenever the client executes a recv() command. As the code stands right now, I cannot get the client to print any data it receives. I cannot figure out whether something is wrong with my server or client, so any help would be appreciated. Thanks!
client.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netdb.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#define ECHO_PORT 9999
#define BUF_SIZE 4096
int main(int argc, char* argv[])
{
if (argc != 3)
{
fprintf(stderr, "usage: %s <server-ip> <port>",argv[0]);
return EXIT_FAILURE;
}
char buf[BUF_SIZE];
int status, sock, sock2;
struct addrinfo hints;
memset(&hints, 0, sizeof(struct addrinfo));
struct addrinfo *servinfo; //will point to the results
hints.ai_family = AF_INET; //IPv4
hints.ai_socktype = SOCK_STREAM; //TCP stream sockets
hints.ai_flags = AI_PASSIVE; //fill in my IP for me
if ((status = getaddrinfo(argv[1], argv[2], &hints, &servinfo)) != 0)
{
fprintf(stderr, "getaddrinfo error: %s \n", gai_strerror(status));
return EXIT_FAILURE;
}
if ((sock = socket(servinfo->ai_family, servinfo->ai_socktype, servinfo->ai_protocol)) == -1)
{
fprintf(stderr, "Socket failed");
return EXIT_FAILURE;
}
if ((connect(sock, (struct sockaddr *) servinfo->ai_addr, servinfo->ai_addrlen)) != 0)
{
fprintf(stderr, "Connection failed");
return EXIT_FAILURE;
}
if ((sock2 = socket(servinfo->ai_family, servinfo->ai_socktype, servinfo->ai_protocol)) == -1)
{
fprintf(stderr, "Socket failed");
return EXIT_FAILURE;
}
if ((connect(sock2, (struct sockaddr *) servinfo->ai_addr, servinfo->ai_addrlen)) != 0)
{
fprintf(stderr, "Connection failed");
return EXIT_FAILURE;
}
while (1) {
//char msg[BUF_SIZE] = "ashudfshuhafhu";
//char msg[BUF_SIZE];
//fgets(msg, BUF_SIZE, stdin);
//int i = 2;
//if (strlen(msg) == i)
// break;
int bytes_received;
// fprintf(stdout, "Sending %s", msg);
//send(sock, msg , strlen(msg), 0);
if((bytes_received = recv(sock, buf, BUF_SIZE, 0)) > 1)
{
buf[bytes_received] = '\0';
fprintf(stdout, "Received %s", buf);
}
}
freeaddrinfo(servinfo);
close(sock);
return EXIT_SUCCESS;
}
Server.c
#include <netinet/in.h>
#include <netinet/ip.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
#define ECHO_PORT 9999
#define BUF_SIZE 4096
int close_socket(int sock)
{
if (close(sock))
{
fprintf(stderr, "Failed closing socket.\n");
return 1;
}
return 0;
}
int main(int argc, char* argv[])
{
int sock, client_sock;
ssize_t readret;
socklen_t cli_size;
struct timeval tv;
struct sockaddr_in addr, cli_addr;
char buf[BUF_SIZE] = "wetwetwetwetwetwetwetwet";
fd_set readfds, writefds;
fd_set activereadfds, activewritefds;
cli_size = sizeof(&cli_addr);
tv.tv_sec = 5;
tv.tv_usec = 0;
fprintf(stdout, "----- Echo Server -----\n");
/* all networked programs must create a socket */
if ((sock = socket(PF_INET, SOCK_STREAM, 0)) == -1)
{
fprintf(stderr, "Failed creating socket.\n");
return EXIT_FAILURE;
}
addr.sin_family = AF_INET;
addr.sin_port = htons(ECHO_PORT);
addr.sin_addr.s_addr = INADDR_ANY;
/* servers bind sockets to ports---notify the OS they accept connections */
if (bind(sock, (struct sockaddr *) &addr, sizeof(addr)))
{
close_socket(sock);
fprintf(stderr, "Failed binding socket.\n");
return EXIT_FAILURE;
}
if (listen(sock, 5))
{
close_socket(sock);
fprintf(stderr, "Error listening on socket.\n");
return EXIT_FAILURE;
}
FD_ZERO(&readfds);
FD_SET(sock, &activereadfds);
while (1)
{
fprintf(stdout,"in here.\n");
readfds = activereadfds;
writefds = activewritefds;
FD_ZERO(&activereadfds);
FD_ZERO(&activewritefds);
if (select(51, &readfds, &writefds, NULL, &tv) < 0)
{
perror("select");
return EXIT_FAILURE;
}
for (int i = 0; i < 10; ++i)
{
if (FD_ISSET (i, &readfds))
{
if (i == sock)
{
fprintf(stdout, "main loop. \n");
client_sock = accept(sock,
(struct sockaddr *) &cli_addr, &cli_size);
FD_SET(client_sock, &activereadfds);
FD_SET(client_sock, &activewritefds);
if (client_sock < 0)
{
perror("accept");
return EXIT_FAILURE;
}
} else {
fprintf(stdout, "second loop \n");
readret = send(i,buf, strlen(buf),0);
if (readret < 0)
fprintf(stdout, "yay");
}
}
if (FD_ISSET(i, &writefds))
{ fprintf(stdout, "ugh \n");
readret = send(i,buf,BUF_SIZE,0);
//if (readret > 0)
//while((readret = recv(i, buf, BUF_SIZE, 0)) >= 1)
// {
//if (send(i, buf, readret, 0) != readret)
//{
// close_socket(i);
// close_socket(sock);
// fprintf(stderr, "Error sending to client.\n");
// return EXIT_FAILURE;
//}
}
}
}
close_socket(sock);
return EXIT_SUCCESS;
}
Your server is sending only when the socket is ready for reading, and as the client is never sending, the server isn't either. The server send should happen when the client socket turns up in the writefds, although actually this isn't the correct way to use that feature. Really you should just send, and only add into and worry about writefds if send() caused EAGAIN/EWOULDBLOCK.
You could be getting an undetected error in the client:
if((bytes_received = recv(sock, buf, BUF_SIZE, 0)) > 1)
{
buf[bytes_received] = '\0';
fprintf(stdout, "Received %s", buf);
}
This should continue:
else if (bytes_received == 0)
{
fprintf(stdout, "peer disconnected\n");
break;
}
else // < 0: error
{
fprintf(stdout, "recv() error %s\n", strerror(errno));
break;
}
You need to print the actual error like this whenever you get an error from a system call.

Problems while implementing HTTP 1.0 server

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"

Resources