How to make server process wait for second read() from FIFO? - c

My server and client are communicating back and forth using two named pipes (fifo) in C until the server receives an exit message.
Apparently the server side blocks the second time it tries to read() from its FIFO despite the client writing to it successfully. I think the problem is that the server tries to read() sooner than the client could write() to it.
Here is the server:
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include "header.h"
#include <sys/stat.h>
#include <errno.h>
#include <sys/types.h>
int main(int argc, char *argv[]) {
//fifo for the server to read from
if (mkfifo(FIFONAME, S_IFIFO|0666) < 0) {
if (errno != EEXIST) {
perror("Error with mkfifo");
exit(1);
}
}
int f;
if ((f = open(FIFONAME, O_RDONLY)) < 0) {
perror("Error with open");
exit(1);
}
Message msg;
while(1) {
if ((read(f, &msg, sizeof(Message))) > 0) {
if (strcmp(msg.user, "exit") == 0) {
close(f);
unlink(FIFONAME);
exit(0);
}
if (strcmp(msg.user, "new client") == 0) {
switch (fork()) {
case -1:{
perror("Error with fork");
exit(1);
}
case 0:{
char gender[MAXLEN];
char client_fifo[30];
sprintf(msg.user, "I need client's gender\n");
sprintf(client_fifo, "fifo_%d", msg.pid);
msg.pid = getpid();
int o;
//open client's fifo for server to write to
if ((o = open(client_fifo, O_WRONLY)) == -1) {
perror("Error opening client fifo");
exit(1);
}
//send message
write(o, &msg, sizeof(Message));
//read client's answer, but program blocks here
if ((read(f, &msg, sizeof(Message))) > 0) {
sprintf(gender,"%s", msg.user);
printf("Client's gender is %s\n", gender);
}
close(o);
exit(0);
}
}
}
}
}
return 0;
}
The client code:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include "header.h"
#include <unistd.h>
int f,fc;
char fifoname[20];
Message msg;
int main(int argc, char* argv[]) {
sprintf(fifoname, "fifo_%d", getpid());
if (mkfifo(fifoname, S_IFIFO | 0666) < 0) {
perror("Error with client's fifo");
printf("Could not create fifo_%d", getpid());
exit(1);
}
if ((f=open(FIFONAME,O_WRONLY))<0) {
perror("Error connecting to server");
exit(2);
}
char gender[MAXLEN];
strcpy(msg.user, "new client");
msg.pid = getpid();
//first message to server
write(f, &msg, sizeof(msg));
char arg[MAXLEN];
if (argc > 1) {
strcpy(arg, argv[1]);
} else {
strcpy(arg, "work");
}
if (strcmp(arg, "exit")) {
if ((fc = open(fifoname, O_RDONLY))<0) {
perror("Error opening client's fifo");
printf("Could not open my fifo");
exit(3);
}
if (read(fc, &msg, sizeof(msg)) > 0) {
printf("%s\n",msg.user);
}
scanf("%s", gender);
strcpy(msg.user, gender);
msg.pid = getpid();
printf("writing gender...\n");
write(f, &msg, sizeof(msg));
//program successfully reaches this print:
printf("gender written\n");
close(fc);
}
unlink(fifoname);
close(f);
exit(0);
}
And the header containing the struct for the message:
#define MAXLEN 20
typedef struct {
int pid;
char user[MAXLEN];
} Message;
#define FIFONAME "fifo_server"
I need to write further back and forth messages like this but I don't know how to get the server not to block on the second call of read()

Related

How to read from named pipe?

I want to create a server client communication through named pipe. Everytime something comes to a server, I want to print the message and run server function - how do I only print when something gets sent? Could someone advise what I am doing wrong in the server file?
server
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
int server(int d) { return d;}
int main()
{
mkfifo("/tmp/myfifo1", 0666);
char buf[256];
for(;;) {
int fd = open("/tmp/myfifo1", O_RDONLY);
int rd = read(fd, buf, sizeof(buf));
if(fd < 0) {
perror("error: open");
}
if(rd < 0) {
perror("error: read");
}
if(rd > 1 ) {
printf("%s", buf);
}
server(5);
close(fd);
}
return 0;
}
client
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
int main()
{
char *buf = "Hello from client";
int fd = open("/tmp/myfifo1", O_WRONLY);
int wr = write(fd, buf, sizeof(buf));
if(fd < 0) {
perror("error: open");
}
if(wr< 0) {
perror("error: write");
close(fd);
return 0;
}

How to extract substring from POSIX message?

I have a server-client program, the client sends the server a message using a struct that has three major values: a date, and two timestamps.
Now, when the server receives the message, I try to extract the date from the message struct as a substring of the character array and then convert it to an int, but I've been stuck for hours now even trying to get the relevant characters from the message.
My server program:
#include "msg.h"
const char *months[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
void delete_mq(char* mname, mqd_t qid) {
if (mq_close(qid) < 0) {
perror("Error closing queue");
exit(1);
}
if (mq_unlink(mname) < 0) {
perror("Error unlinking queue");
exit(1);
}
}
void make_command(MESSAGE *mess, char *mname, mqd_t qid) {
printf("making command, hehe\n");
if (strcmp(mess->date,"STOP") == 0){
printf("Stopping the server.\n");
delete_mq(mname, qid);
exit(0);
}
// this is where I am stuck
char thedate[3];
char *date = mess->date;
strncpy(thedate, date+1, 1);
thedate[2] = '\0';
printf("%s\n", thedate);
strcpy(mess->messtext,"Some text respone message");
}
int main(int argc, char** argv)
{
int flagsc = O_RDONLY | O_CREAT;
mode_t mode = 0600;
struct mq_attr attr;
attr.mq_flags = 0;
attr.mq_maxmsg = 10;
attr.mq_msgsize = sizeof(MESSAGE);
attr.mq_curmsgs = 0;
int flags = O_WRONLY;
char cname[10];
char sqname[15];
sprintf(sqname,"%s%s",qname,getlogin());
mqd_t qid = mq_open(sqname, flagsc, mode, &attr);
if (qid <0) {
perror("Error opening message queue");
exit(1);
}
for (;;) {
MESSAGE message;
unsigned int priority = 0;
if (mq_receive(qid, (char*) &message, sizeof(message), &priority) != -1) {
make_command(&message, qname, qid);
sprintf(cname,"/%d", message.pid);
message.pid = getpid();
mqd_t cmqid = mq_open(cname, flags);
mq_send(cmqid, (char*)&message, sizeof(MESSAGE), 0);
mq_close(cmqid);
}
}
mq_close(qid);
return 0;
}
My client program:
// ./client 11.23. 13:24 16:43
#include "msg.h"
int main(int argc, char** argv)
{
if (argc != 4){
printf("Usage: ./client <date e.g. 11.23.> <time1 e.g. 13:24> <time2 e.g. 16:43>\n");
exit(1);
}
int flags = O_WRONLY;
int cflags = O_RDONLY|O_CREAT;
mode_t mode = 0600;
char sqname[15];
sprintf(sqname,"%s%s", qname, getlogin());
mqd_t qid = mq_open(sqname, flags);
if (qid == -1) {
perror("Error opening queue in client");
exit(1);
}
struct mq_attr temp;
if (mq_getattr(qid, &temp) == -1) {
perror("Error with getattr in client");
} else {
// finish later
}
char cqname[20];
struct mq_attr attr;
attr.mq_flags = 0;
attr.mq_maxmsg = 8;
attr.mq_msgsize = sizeof(MESSAGE);
attr.mq_curmsgs = 0;
sprintf(cqname,"/%d", getpid());
mqd_t cqid = mq_open(cqname, cflags, mode, &attr);
if (cqid == -1) {
perror("Error opening queue in client");
exit(1);
}
MESSAGE mess;
strcat(mess.date, argv[1]);
strcat(mess.time1, argv[2]);
strcat(mess.time2, argv[3]);
mess.pid = getpid();
printf("Client has sent request");
if (mq_send(qid, (char*) &mess, sizeof(MESSAGE), 0) < 0) {
perror("Error sending message in client");
exit(1);
}
if (strcmp(mess.date,"STOP") != 0) {
if (mq_receive(cqid,(char*) &mess, sizeof(MESSAGE), 0) < 0) {
perror("Error receiving message in client");
exit(1);
}
} else {
printf("Stopping the client.\n");
if(mq_close(qid) < 0) {
perror("error closing server queue");
exit(1);
}
if(mq_close(cqid) < 0) {
perror("error closing client queue");
exit(1);
}
if (mq_unlink(cqname) < 0) {
perror("Error unlinking client queue");
exit(1);
}
exit(0);
}
printf("%s\n", mess.messtext);
if(mq_close(qid) < 0) {
perror("error closing server queue");
exit(1);
}
if(mq_close(cqid) < 0) {
perror("error closing client queue");
exit(1);
}
if (mq_unlink(cqname) < 0) {
perror("Error unlinking client queue");
exit(1);
}
exit(0);
}
And the header:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <unistd.h>
#include <mqueue.h>
#define KEY 1111
typedef struct{
int pid;
// e.g. 11.23.
char date[50];
char time1[50];
char time2[50];
char messtext[10];
} MESSAGE;
char * qname="/server_";
Now, the arguments for a client execution should be a date, and two timestamps. When the server receives the message, I want to extract the first two characters from date (the month) and convert it to int so that I could get the relevant month from *months[].
I tried pretty much everything: strcpy, memcpy, sprintf and I'm going nuts, because it will either only print the first number of the month, or won't convert correctly, or print extra crazy characters from memory, and I've barely started to break the message down into parts. The mess->date apparently has some other character on its first position, and I can't manage to skip it.
Could someone help me achieve what I described?

Download a file from server using TCP

I'm trying to write a C program for a client which can download a file from the server using TCP. The client will print and save the file content after it receives the file from the server. To compile the client program it needs IP address and port number of the server. I implemented it in Linux but it displayed 0s after the received texts. The saved text file was the same. I have no idea how to output the text only. Maybe there are wrongs in the receive buffer?
Code for server:
#include <stdio.h>
#include <netdb.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <pthread.h>
#define portnum 12345
#define FILE_SIZE 500
#define BUFFER_SIZE 1024
void *client_fun(void * fd);
int main()
{
int new_fd;
pthread_t thread_id;
int server_fd=socket(AF_INET,SOCK_STREAM,0);
if(-1==server_fd)
{
perror("socket");
exit(1);
}
struct sockaddr_in server_addr;
server_addr.sin_family=AF_INET;
server_addr.sin_port=htons(portnum);
(server_addr.sin_addr).s_addr=htonl(INADDR_ANY);
if(-1==bind(server_fd,(struct sockaddr *)&server_addr,sizeof(server_addr)))
{
perror("bind");
close(server_fd);
exit(6);
}
if(-1==listen(server_fd,5))
{
perror("listen");
close(server_fd);
exit(7);
}
while(1)
{
struct sockaddr_in client_addr;
int size=sizeof(client_addr);
new_fd=accept(server_fd,(struct sockaddr *)&client_addr,&size);
if(new_fd < 0)
{
perror("accept");
continue;
}
printf("accept client ipé”›?s:%d\n",inet_ntoa(client_addr.sin_addr),client_addr.sin_port);
//printf("new_fd=%d\n",new_fd);
if (new_fd > 0)
{
pthread_create(&thread_id, NULL, client_fun, (void *)&new_fd);
pthread_detach(thread_id);
}
}
close(server_fd);
return 0;
}
void *client_fun(void *arg)
{
int new_fd = *((int *)arg);
int file2_fp;
int len;
char buffer[BUFFER_SIZE];
memset( buffer,0, sizeof(buffer) );
while(1)
{
if((len=recv(new_fd, buffer, sizeof(buffer), 0)) <= 0)
{
continue;
}
char file_name[FILE_SIZE];
memset( file_name,0, sizeof(file_name) );
strncpy(file_name, buffer, strlen(buffer)>FILE_SIZE?FILE_SIZE:strlen(buffer));
memset( buffer,0, sizeof(buffer) );
printf("Client requests file %s\n", file_name);
if( strcmp(file_name,"exit")==0 )
{
break;
}
file2_fp = open(file_name,O_RDONLY,0777);
if(file2_fp<0)
{
printf("File %s Not Found\n", file_name);
char* err_info = "File not found\n";
if (write(new_fd, err_info, sizeof(err_info)) < 0)
{
printf("Send error information failed\n");
break;
}
continue;
}
else
{
int length = 0;
memset( buffer,0, sizeof(buffer) );
while( (length = read(file2_fp, buffer, sizeof(buffer))) > 0 )
{
if( write(new_fd, buffer, length) < 0)
{
printf("Send File %s Failed.\n", file_name);
break;
}
memset( buffer,0, sizeof(buffer) );
}
close(file2_fp);
printf("Transfer file %s successfully!\n", file_name);
}
}
close(new_fd);
}
Code for client:
#include <stdio.h>
#include <netdb.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <pthread.h>
int main(int argc, char *argv[])
{
int sockfd = 0;
char recvBuff[1024];
char file_name[500];
char *serverIP=argv[1];
int portno=atoi(argv[2]);
printf("IP Addresses: %s Port Number: %s\n", argv[1], argv[2]);
memset(recvBuff,'0',sizeof(recvBuff));
struct sockaddr_in server_addr;
/* Creat a socket*/
sockfd = socket(AF_INET, SOCK_STREAM, 0);
/*Initialize sockaddr_in structure*/
server_addr.sin_family=AF_INET;
server_addr.sin_port=htons(portno);
(server_addr.sin_addr).s_addr=inet_addr(serverIP);
/*Attempt a connection*/
printf("Connect status: ");
if (connect(sockfd,(struct sockaddr *)&server_addr,sizeof(server_addr))<0)
{
printf("fail\n");
return 0;
}
printf("success\n");
/*Request file from server*/
while(1)
{
printf("Input the file name to be requested from the server: ");
fgets(file_name,500, stdin);
char *p=strchr(file_name,'\n');
if (p) *p=0;
if (send(sockfd, file_name, strlen(file_name), 0)<0)
{
printf("Send failed.\n");
break;
}
printf("Send success.\n");
if (strcmp(file_name,"exit")==0)
break;
int length=0;
printf("Send status: ");
if (length=read(sockfd, recvBuff, sizeof(recvBuff))<0)
{
printf("fail\n");
continue;
}
else if (strcmp(recvBuff,"File not found\n")==0)
{
printf("fail\n");
continue;
}
else
{
printf("success\n");
/*Create file where text will be stored*/
FILE *fp;
fp=fopen("received_file.txt","w");
printf("Open file status: ");
if (fp==NULL)
{
printf("fail\n");
continue;
}
printf("success\n");
printf("Received text: ");
if (fprintf(fp, "%s", recvBuff)<0)
{
printf("Save status: fail\n");
continue;
}
fflush(fp);
printf("%s",recvBuff);
memset(recvBuff,0,1024);
while ((length=read(sockfd, recvBuff, sizeof(recvBuff)))>0)
{
if (fprintf(fp, "%s", recvBuff)<0)
{
printf("Save status: fail\n");
break;
}
fflush(fp);
printf("%s",recvBuff);
memset(recvBuff,0,1024);
}
printf("Save status: success");
}
}
}
Another question is that the client is supposed to keep asking for files until it sends an 'exit'. But it stopped asking the client to input the file name after the first file was received. What's wrong with the loop?
you have several issues.
first: - comparison operator has precedence over assignment so length gets FALSE(0) value instead of the real number of received data
if (length=read(sockfd, recvBuff, sizeof(recvBuff))<0)
it should be:
if ((length=read(sockfd, recvBuff, sizeof(recvBuff)))<0)
second: you are operating with zero terminated strings but you do not send zero ('\0') from server and client does not set it at the end of the data block.
So you need to set it explicitly at client side here
if ((length=read(sockfd, recvBuff, sizeof(recvBuff)))<0)
{
printf("fail\n");
continue;
}
else if (strcmp(recvBuff,"File not found\n")==0)
{
printf("fail\n");
continue;
}
else
{
recvBuff[length]='\0';
and here:
while ((length=read(sockfd, recvBuff, sizeof(recvBuff)))>0){
recvBuff[length]='\0';

c socket file transfer, server does not open existing file

I am writing simple client-server program. Essentially I am following example from "Linux Network Programming" book. This is simple TCP server
#include <stdio.h>
#include <fcntl.h>
#include <sys/types.h>
#include <netdb.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <string.h>
#define SERVERPORT 8888
#define MAXBUF 1024
int main(int argc, char* argv[])
{
int socket1, socket2;
int addrlen;
struct sockaddr_in fServer, fClient;
int status;
socket1=socket(AF_INET, SOCK_STREAM, 0);
if(socket1==-1)
{
printf("Could not create the socket\n");
exit(1);
}
fServer.sin_family=AF_INET;
fServer.sin_addr.s_addr=INADDR_ANY;
fServer.sin_port= htons(SERVERPORT);
status=bind(socket1, (struct sockaddr*) &fServer,
sizeof(fServer));
if(status==-1)
{
printf("could not bind the socket\n");
exit(1);
}
else printf("socket is created\n");
status=listen(socket1, 5);
if(status==-1)
{
printf("could not listen socket\n");
exit(1);
}
else printf("socket is waiting for connection\n");
for(;;)
{
int fd;
int i, readCounter, writeCounter;
char* bufptr;
char buf[MAXBUF];
char filename[MAXBUF];
addrlen=sizeof(fClient);
socket2=accept(socket1, (struct sockaddr*) &fClient, &addrlen);
if(socket2==-1)
{
printf("could not accept connection\n");
exit(1);
}
else printf("connection established, waiting for the file name\n");
i=0;
if((readCounter=read(socket2, filename, MAXBUF))>0)
i+=readCounter;
filename[i+1]='\0';
printf("reading from the file\n");
fd=open(filename, O_RDONLY);
if(fd==-1)
{
printf("could not open the file\n");
perror(" error is detected: ");
close(socket2);
continue;
}
else printf("file name is recieved, started copying\n");
readCounter=0;
while((readCounter=read(fd, buf, MAXBUF))>0)
{
writeCounter=0;
bufptr=buf;
while(writeCounter<readCounter)
{
readCounter-=writeCounter;
bufptr+=writeCounter;
writeCounter=write(socket2, bufptr, readCounter);
if(writeCounter==-1)
{
printf("could not write the file to client\n");
close(socket2);
continue;
}
}
}
close(fd);
close(socket2);
}
close(socket1);
return 0;
}
This code is for client.
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdio.h>
#include <sys/types.h>
#include <fcntl.h>
#include <stdlib.h>
#define SERVERPORT 8888
#define MAXBUF 1024
int main(int argc, char* argv[])
{
int sockd;
int counter;
int fd;
struct sockaddr_in fServer;
char buf[MAXBUF];
int status;
if(argc<3)
{
printf("Incorrect data provided\n");
exit(1);
}
sockd=socket(AF_INET, SOCK_STREAM,0);
if(sockd==-1)
{
printf("could not create socket\n");
exit(1);
}
fServer.sin_family=AF_INET;
fServer.sin_addr.s_addr=inet_addr(argv[1]);
fServer.sin_port=htons(SERVERPORT);
status=connect(sockd, (struct sockaddr*)&fServer,
sizeof(fServer));
if(status==-1)
{
printf("could not connect to server\n");
exit(1);
}
status=write(sockd, argv[2], strlen(argv[2]+1));
if(status==-1)
{
printf("could not send file name to server\n");
exit(1);
}
shutdown(sockd, SHUT_WR);
fd=open(argv[2], O_WRONLY| O_CREAT| O_APPEND);
if(fd==-1)
{
printf("could not open destination file\n");
exit(1);
}
while((counter=read(sockd, buf, MAXBUF))>0)
{
write(fd, buf, counter);
}
if(counter==-1)
{
printf("file transfer is complete\n");
exit(1);
}
printf("file transfer is complete\n");
close(sockd);
return 0;
}
I pass file name from the same directory as server. I pass filename as agrc[2] parameter. Server oputput however is the following
socket is created
socket is waiting for connection
connection established, waiting for the file name
reading from the file
could not open the file
error is detected: : No such file or directory
connection established, waiting for the file name
reading from the file
could not open the file
error is detected: : No such file or directory
I entered the filename on my first attempt, then I enterd full path but still recieving the same message. So what is the problem? thanks in advance
Client:
status=write(sockd, argv[2], strlen(argv[2]+1));
strlen(argv[2]+1) should be strlen(argv[2])+1 if you want to include the \0.also: you do not close your fd. close(sockd); should be close(fd);
Server:
filename[i+1]='\0'; should be filename[i]='\0'; if you are not sure you received the \0.
if you are sending 1 char, for example 'a', i would be 1 and your array would look like
filename[0] = 'a'
filename[i] = undefined
filename[i+1] = '\0'
Unrelated to your problem, but on the server side you should advance bufptr after write(), not before.
Also: TCP is a stream protocol; there is no guarantee that a write() on one end of a connection will be completely read by a single recv() on the other end.

Processes not terminating

There are some strange things happening in my client-server application. Please, look at these simple fork client/server:
CLIENT:
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <time.h>
#include <arpa/inet.h>
#include <string.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <errno.h>
#include <sys/time.h>
#include <sys/wait.h>
#define IP_SERVER "192.168.1.89"
#define PORT_SERVER 65000
#define BUFFERSIZE 1024
#define NUMFILES 3
double timeElapsed(struct timeval* before, struct timeval* after) {
return after->tv_sec - before->tv_sec + (double) (after->tv_usec - before->tv_usec)/1000000;
}
void getFile(char *request, struct sockaddr_in server) {
char buffer[1024];
int sockProc, res;
int file;
int sizeServ = sizeof(server);
int writeFile;
sockProc = socket(AF_INET, SOCK_STREAM, 0);
if (sockProc < 0) {
printf("Error on creating socket client\n");
perror("");
exit(1);
}
file = open(request, O_CREAT | O_WRONLY, S_IRWXU);
res = connect(sockProc, (struct sockaddr*)&server, (socklen_t)sizeServ);
if (res < 0) {
printf("Error on connecting to server!\n");
perror("");
exit(1);
}
res = send(sockProc, (void*)request, strlen(request), 0);
memset(buffer, 0, sizeof(buffer));
while((res = recv(sockProc, (void*)buffer, sizeof(buffer), 0)) > 0) {
write(file, (void*)buffer, strlen(buffer));
memset(buffer, 0, sizeof(buffer));
}
close(sockProc);
close(file);
return;
}
int main(int argc, char** argv) {
int sockCli, res, i;
struct sockaddr_in server;
int sizeServ = sizeof(server);
memset(&server, 0, sizeof(server));
server.sin_family = AF_INET;
inet_pton(AF_INET, IP_SERVER, &server.sin_addr);
server.sin_port = htons(PORT_SERVER);
char files[NUMFILES][32];
char nameFile[32];
char command[32] = "rm *.txt";
system(command);
struct timeval begin;
struct timeval end;
pid_t processes[NUMFILES];
for(i = 0; i<NUMFILES; i++) {
memset(nameFile, 0, sizeof(nameFile));
printf("Inserisci nome file (con estensione) da ricevere:\n");
scanf("%s", nameFile);
strcpy(files[i], nameFile);
}
gettimeofday(&begin, NULL);
for(i=0; i<NUMFILES; i++) {
pid_t child = fork();
if(child == 0) {
getFile(files[i], server);
exit(0);
}
else {
processes[i] = child;
continue;
}
}
/*for(i=0; i<NUMFILES; i++) {
waitpid(processes[i], NULL, 0);
}*/
wait(NULL);
gettimeofday(&end, NULL);
printf("Time elapsed on TCP is %f seconds\n", timeElapsed(&begin, &end));
return 0;
}
and the SERVER:
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <time.h>
#include <arpa/inet.h>
#include <string.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#define IP_SERVER "192.168.1.89"
#define PORT_SERVER 65000
#define BUFFERSIZE 1024
void execRequest(int* sockCli, struct sockaddr_in* client) {
char buffer[BUFFERSIZE];
char request[BUFFERSIZE];
int res;
memset(request, 0, sizeof(request));
res = recv(*sockCli, (void*)request, sizeof(request), 0);
if(res < 0) {
printf("Error on recv()\n");
perror("");
exit(1);
}
printf("Requested file %s\n", request);
char resource[32] = "files/";
strcat(resource, request);
int file = open(resource, O_RDONLY);
if (file < 0) {
printf("File %s does not exist\n", request);
exit(1);
}
memset(buffer, 0, sizeof(buffer));
while((res = read(file, (void*)buffer, sizeof(buffer))) > 0) {
send(*sockCli, (void*)buffer, strlen(buffer), 0);
memset(buffer, 0, sizeof(buffer));
}
close((*sockCli));
close(file);
free(sockCli);
free(client);
return;
}
int main(int argc, char** argv) {
int sockServ, i, res;
int *sockCli;
struct sockaddr_in server;
struct sockaddr_in* client;
sockServ = socket(AF_INET, SOCK_STREAM, 0);
if(sockServ < 0) {
printf("Error in creating socket\n");
perror("");
exit(1);
}
memset(&server, 0, sizeof(server));
server.sin_addr.s_addr = inet_addr(IP_SERVER);
server.sin_port = htons(PORT_SERVER);
server.sin_family = AF_INET;
int reuse = 1;
res = setsockopt(sockServ, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(int));
if (res < 0) {
printf("setsockopt() REUSEADDR failed\n");
perror("");
exit(1);
}
res = bind(sockServ, (struct sockaddr*)&server, sizeof(server));
if (res < 0) {
printf("Error on bindind TCP server!\n");
perror("");
exit(1);
}
res = listen(sockServ, 5);
if (res < 0) {
printf("Error on listening TCP server!\n");
perror("");
exit(1);
}
while(1) {
sockCli = (int*)malloc(sizeof(int));
client = (struct sockaddr_in*)malloc(sizeof(struct sockaddr_in));
int sizeClient = sizeof(struct sockaddr_in);
*sockCli = accept(sockServ, (struct sockaddr*)client, &sizeClient);
if ((*sockCli) < 0) {
printf("accept() failed\n");
perror("");
continue;
}
printf("Connected to %s:%d\n", inet_ntoa(client->sin_addr), client->sin_port);
if( !fork() ) {
execRequest(sockCli, client);
exit(0);
}
else
continue;
}
return 0;
}
This is very strange. The processes created by the client don't terminate even if the server closes the sockets and so recv() should return 0 and let client processes exit from the loop. Moreover there's something strange about reading files:
the server simply reads files.txt but in doing this it includes the string ".txt" in the read characters and sends all this mixture to the client...why?
they are simple file mono character like
aaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaa
but the server reads and and sends:
aaaaaaaaaaaaaaaaaa.txt
aaaaaaaaaaaaaaaaaa
can I solve all this?
You can't use strlen(buffer), just because you're loading characters from a text file doesn't mean that buffer will be a valid string unless you take steps to ensure it is. And you don't; there's no termination since you can fill all of buffer with data from the file.
How many times must we play the broken record here on Stack Overflow? Don't cast malloc!
I chalk this error to failure to read the manual(s), to find out what header to include, what a string is (and hence what strlen/strcat/str*{anything}* expects of its input, what printf expects of arguments that correspond to a %s format specifier, etc.) and what read/recv produces.
res = recv(*sockCli, (void*)request, sizeof(request), 0);
if(res < 0) {
printf("Error on recv()\n");
perror("");
exit(1);
}
printf("Requested file %.*s\n", res, request); // NOTE the field width provided by 'res'
By the manual, examples such as res = read(file, (void*)buffer, sizeof(buffer)) supposedly store either an error or a length. The condition ensures that the send code will only execute when it's a length value, so why not use it as one? send(*sockCli, (void*)buffer, res, 0);?
The presense of these problems seems to indicate that your method of learning isn't working. Which book are you reading? Learning C without a book is a bit like learning which berries are poisonous without communication.

Resources