Related
The exercise ask to resend the messages back to the client.
This exercise with some pieces of code were provided by our teacher.
I don't know why the last message that the program send does not appear. I can't understand where is the error.
I have changed the read adding the & before x. Now the x value is displayed correctly but the last value is still missing
When I insert only one value the message is missing.
The server is always running and I don't know how to fix this.
The server code is:
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
/*const*/ char MESSAGE[100] = "";
char buff[100];
int main(int argc, char *argv[]) {
int simpleSocket = 0;
int simplePort = 0;
int returnStatus = 0;
struct sockaddr_in simpleServer;
if (argc != 2) {
fprintf(stderr, "Usage: %s <port>\n", argv[0]);
exit(1);
}
simpleSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (simpleSocket == -1) {
fprintf(stderr, "Could not create a socket!\n");
exit(1);
}
else {
fprintf(stderr, "Socket created!\n");
}
/* retrieve the port number for listening */
simplePort = atoi(argv[1]);
/* setup the address structure */
/* use INADDR_ANY to bind to all local addresses */
memset(&simpleServer, '\0', sizeof(simpleServer));
simpleServer.sin_family = AF_INET;
simpleServer.sin_addr.s_addr = htonl(INADDR_ANY);
simpleServer.sin_port = htons(simplePort);
/* bind to the address and port with our socket */
returnStatus = bind(simpleSocket,(struct sockaddr *)&simpleServer,sizeof(simpleServer));
if (returnStatus == 0) {
fprintf(stderr, "Bind completed!\n");
}
else {
fprintf(stderr, "Could not bind to address!\n");
close(simpleSocket);
exit(1);
}
/* lets listen on the socket for connections */
returnStatus = listen(simpleSocket, 5);
if (returnStatus == -1) {
fprintf(stderr, "Cannot listen on socket!\n");
close(simpleSocket);
exit(1);
}
int x;
int i=0;
while (1)
{
struct sockaddr_in clientName = { 0 };
int simpleChildSocket = 0;
int clientNameLength = sizeof(clientName);
/* wait here */
simpleChildSocket = accept(simpleSocket,(struct sockaddr *)&clientName, &clientNameLength);
if (simpleChildSocket == -1) {
fprintf(stderr, "Cannot accept connections!\n");
close(simpleSocket);
exit(1);
}
/* handle the new connection request */
/* write out our message to the client */
//read the number of messages that have to be send
read(simpleChildSocket, &x, sizeof(x));
printf("x value is: %d\n", x);
do{
// read the message from client and copy it in buffer
read(simpleChildSocket, buff, sizeof(buff));
//copy buff in MESSAGE
strcpy(MESSAGE, buff);
//sending the message
write(simpleChildSocket, MESSAGE, strlen(MESSAGE));
//cleaning the buffer
memset(&simpleServer, '\0', sizeof(simpleServer));
i++;
}while(i<x);
close(simpleChildSocket);
}
close(simpleSocket);
return 0;
}
The client code is:
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
int main(int argc, char *argv[]) {
int simpleSocket = 0;
int simplePort = 0;
int returnStatus = 0;
char buffer[256] = "";
struct sockaddr_in simpleServer;
if (argc != 3) {
fprintf(stderr, "Usage: %s <server> <port>\n", argv[0]);
exit(1);
}
/* create a streaming socket */
simpleSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (simpleSocket == -1) {
fprintf(stderr, "Could not create a socket!\n");
exit(1);
}
else {
fprintf(stderr, "Socket created!\n");
}
/* retrieve the port number for connecting */
simplePort = atoi(argv[2]);
/* setup the address structure */
/* use the IP address sent as an argument for the server address */
//bzero(&simpleServer, sizeof(simpleServer));
memset(&simpleServer, '\0', sizeof(simpleServer));
simpleServer.sin_family = AF_INET;
//inet_addr(argv[2], &simpleServer.sin_addr.s_addr);
simpleServer.sin_addr.s_addr=inet_addr(argv[1]);
simpleServer.sin_port = htons(simplePort);
/* connect to the address and port with our socket */
returnStatus = connect(simpleSocket, (struct sockaddr *)&simpleServer, sizeof(simpleServer));
if (returnStatus == 0) {
fprintf(stderr, "Connect successful!\n");
}
else {
fprintf(stderr, "Could not connect to address!\n");
close(simpleSocket);
exit(1);
}
/*create the message*/
char buff[100];
int i=0, x;
//int n;
//while((buff[n++] = getchar()) != '\n');
printf("How many messages do you want to send?\n");
scanf("%d", &x);
write(simpleSocket, x, sizeof(x));
printf("Insert the message:\n");
do{
fgets(buff, 100, stdin);
write(simpleSocket, buff, sizeof(buff));
i++;
}while(i<=x);
/* get the message from the server */
returnStatus = read(simpleSocket, buffer, sizeof(buffer));
if ( returnStatus > 0 ) {
printf("%d: %s", returnStatus, buffer);
} else {
fprintf(stderr, "Return Status = %d \n", returnStatus);
}
close(simpleSocket);
return 0;
}
You have an issue with read.
This should be :
read(simpleChildSocket, &x, sizeof(x));
Read is expecting a pointer.
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;
}
I have a question about socket.I send N-size data from client to server, N-size less than 100 byte.So I think my data should not be split to multiple tcp packet.In my opinion, Client send data should be done at one times and Server can receive data at one time.But The result is not satisfactory.Real situation is the server need call read data.I don't understand it.Follow code:
epoll_server.cpp(only receive data.)
#include <sys/socket.h>
#include <stdio.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/epoll.h>
#include <fcntl.h>
#include <netdb.h>
#define BUFSIZE 1024
#define INITSIZE 1024
#define MAXEVENTCOUNT 10240
// add non-blocking to sockfd
int make_socket_non_blocking(int fd)
{
// get initial flag
int src_flags;
src_flags= fcntl(fd, F_GETFL,0);
if(src_flags == -1)
{
perror("fcntl get error.");
return-1;
}
// add non-blocking
int new_flags = src_flags | O_NONBLOCK;
int ret_value;
ret_value = fcntl(fd, F_SETFL, new_flags);
if(ret_value == -1)
{
perror("fcntl set error.");
return-1;
}
return 0;
}
// main function
int main(int argc, char* argv[])
{
int server_sockfd, client_sockfd;
int server_len;
struct sockaddr_in server_address;
// create server socket fd
server_sockfd = socket(AF_INET, SOCK_STREAM, 0);
// init server address struct
bzero(&server_address, sizeof(server_address));
server_address.sin_family = AF_INET;
server_address.sin_port = htons(9567);
server_address.sin_addr.s_addr = INADDR_ANY;
server_len = sizeof(server_address);
// bind server address info for server fd
if((bind(server_sockfd, (struct sockaddr*)&server_address, server_len)) == -1)
{
perror("bind error");
exit(EXIT_FAILURE);
}
// let server is listened state
listen(server_sockfd, 5);
printf("server start waiting for connect...\r\n");
// only suggestion
int efd = epoll_create(INITSIZE);
if(-1 == efd)
{
printf("epoll_create error happen.\n");
return -1;
}
// set server_sockfd
struct epoll_event server_event, event;
server_event.data.fd = server_sockfd;
server_event.events = EPOLLIN | EPOLLET;
int ret_epollctl = epoll_ctl(efd, EPOLL_CTL_ADD, server_sockfd, &server_event);
if(-1 == ret_epollctl)
{
printf("epoll_ctl error happen when efd is adding server_sockfd.\n");
return -1;
}
/* event loop */
struct epoll_event* return_events;
// set timeout is 3000 ms
int timeout_msecond = 3000;
return_events = (struct epoll_event*)malloc(MAXEVENTCOUNT*sizeof(struct epoll_event));
int count = 0;
while(1)
{
int ret_epollwait = epoll_wait(efd, return_events, MAXEVENTCOUNT, timeout_msecond);
// part_1:epoll_wait error happen
if(-1 == ret_epollwait)
{
printf("logged epoll_wait error happen.\n");
continue;
}
// part_2:epoll_wait timeout
if(0 == ret_epollwait)
{
printf("logged epoll_wait timeout.\n");
continue;
}
// part_3:do some other event
int index = 0;
for(index = 0; index < MAXEVENTCOUNT; index++)
{
// part_3-1:hup ...
if((return_events[index].events & EPOLLERR)
|| (return_events[index].events & EPOLLHUP)
|| !(return_events[index].events & EPOLLIN) )
{
continue;
}
// part_3-2:is connection
if(return_events[index].data.fd == server_sockfd)
{
struct sockaddr_in client_address;
int client_len = sizeof(client_address);
// server accept connection from client
int client_sockfd = accept(server_sockfd, (struct sockaddr*)&client_address, (socklen_t*)&client_len);
// part_3-2-1:connection error happen
if(-1 == client_sockfd)
{
if((EAGAIN == errno)
|| (EWOULDBLOCK == errno) )
{
continue;
}
else
{
printf("accept error occured.\n");
continue;
}
}
else // part_3-2-2:normal connection
{
// get clinet some information
char hostinfo_buf[BUFSIZE] = {0};
char servname_buf[BUFSIZE] = {0};
int tmp_ret = getnameinfo((struct sockaddr*)&client_address, client_len, hostinfo_buf, sizeof(hostinfo_buf), servname_buf, sizeof(servname_buf), NI_NUMERICHOST| NI_NUMERICSERV);
if(0 == tmp_ret)
{
printf("Accepted connection on descriptor %d:ip=%s, port=%s.\n", client_sockfd, hostinfo_buf, servname_buf);
}
// set client_sockfd to non-blocking
tmp_ret = make_socket_non_blocking(client_sockfd);
if(-1 == tmp_ret)
{
printf("set client_sockfd=%d to non-blocking error occured.\n", client_sockfd);
abort();
}
// set client_sockfd is EPOLLIN, EPOLLET
event.data.fd = client_sockfd;
event.events = EPOLLIN | EPOLLET;
tmp_ret = epoll_ctl(efd, EPOLL_CTL_ADD, client_sockfd, &event);
if(tmp_ret == -1)
{
printf("efd add %d has a error.\n", client_sockfd);
continue;
}
printf("add descriptor %d:ip=%s, port=%s successfully.\n", client_sockfd, hostinfo_buf, servname_buf);
}
continue;
}
// part_3-3:read data from client
printf("read data start++++\n");
int temp = 0;
// get recv_cache size start
int recvsize = 0;
socklen_t optlen = sizeof(recvsize);
int err = getsockopt(return_events[index].data.fd, SOL_SOCKET, SO_RCVBUF, &recvsize, &optlen);
printf("recv cache size :%d\n", recvsize);
// get recv_cache size end
while(1) // start while(1)
{
printf("%d times read data\n", ++temp);
char* recv_buffer = (char*)malloc(1024+1);
memset(recv_buffer, 0, 1025);
// int ret_read = read(return_events[index].data.fd, recv_buffer, sizeof(recv_buffer));
int ret_read = recv(return_events[index].data.fd, recv_buffer, sizeof(recv_buffer), 0);
// part_3-3-1:read return error
if(-1 == ret_read)
{
if(EAGAIN != errno)
{
printf("read data from %d error occured, errno=%d, %s.\n", return_events[index].data.fd, errno, strerror(errno));
}
break;
}
// part_3-3-2:no data
if(0 == ret_read)
{
continue;
}
// part_3-3-3:output data. If data is 'bye', connection will close.
if(ret_read > 0)
{
printf("%d client's data:size=%dbyte, content=%s\n", return_events[index].data.fd, ret_read, recv_buffer);
// part_3-3-3-1:close connection and remove client_sockfd
if((recv_buffer[0] == 'b')
&& (recv_buffer[1] == 'y')
&& (recv_buffer[2] == 'e') )
{
close(return_events[index].data.fd);
printf("close %d, ", return_events[index].data.fd);
int tmp_ret = epoll_ctl(efd, EPOLL_CTL_DEL, return_events[index].data.fd, NULL);
if(tmp_ret == -1)
{
printf("efd del %d has a error.\n", client_sockfd);
}
printf("remove descriptor %d successfully.\n", return_events[index].data.fd);
}
}
} // end of while(1)
printf("read data finish------\n");
}
}
free(return_events);
// close server_sockfd
shutdown(server_sockfd, 2);
return 0;
}
epoll_client.cpp(only send data.)
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/socket.h>
#include <resolv.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <fcntl.h>
#define BUFSIZE 1024
int main(int argc, char* argv[])
{
int sock_clientfd, ret_recvsize, i;
struct sockaddr_in dest, mine;
char send_buffer[BUFSIZE + 1];
// create socket fd
if ((sock_clientfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
perror("Socket");
exit(EXIT_FAILURE);
}
// init server address that client will connetct to.
bzero(&dest, sizeof(dest));
dest.sin_family = AF_INET;
dest.sin_port = htons(9567);
if(argc != 2)
{
printf("Usage: %s <dest ip>\n", argv[0]);
printf("Usage: %s 127.0.0.1\n", argv[0]);
return -1;
}
printf("-----\n");
if (inet_aton(argv[1], (struct in_addr *) &dest.sin_addr.s_addr) == 0)
{
perror(argv[1]);
exit(1);
}
// connect to server
printf("will connect!\n");
if (connect(sock_clientfd, (struct sockaddr *) &dest, sizeof(dest)) != 0)
{
perror("Connect ");
exit(EXIT_FAILURE);
}
while(1)
{
bzero(send_buffer, BUFSIZE + 1);
printf("input message:");
fgets(send_buffer, BUFSIZE, stdin);
send_buffer[strlen(send_buffer) - 1] = '\0';
printf("%d\n", strlen(send_buffer));
int send_retsize = send(sock_clientfd, send_buffer, strlen(send_buffer), 0);
if(send_retsize == -1)
{
perror("send data to client error happen!");
exit(EXIT_FAILURE);
}
printf("send succ data:%s\n", send_buffer);
if((send_buffer[0] == 'b')
&& (send_buffer[1] == 'y')
&& (send_buffer[2] == 'e') )
{
printf("client active close connect.\n");
break;
}
}
// close sock_clientfd
close(sock_clientfd);
return 0;
}
Follow pircture is some run info:
epoll_server.png
epoll_client.png
The server read data is only 8 byte, Is the kernel design epoll is this?
I guess the reasons are as follows pirture:
The reason you don't receive everything that is available in one read is because you only read 8 bytes at a time.
char* recv_buffer = (char*)malloc(1024+1);
int ret_read = recv(return_events[index].data.fd, recv_buffer, sizeof(recv_buffer), 0);
// part_3-3-1:read return error
recv_buffer is a char* not an array, so sizeof recv_buffer equals the size of a pointer which in your case is 8.
Note that you should never rely on data arriving in packages. If your message protocol states that you should be getting 10 bytes never expect all 10 bytes to be available at once. You should always code in a way that can handle data being split up into multiple reads.
If the thread handles a single socket then a simple do { read... } while (total_bytes_received < expected_bytes); will suffice.
If the thread handles multiple connections, then you need to save the bytes you have read and then continue to manage other sockets that are ready before returning to your handling loop that will use select/epoll to wait for more data.
I am trying to make a multi-threaded server-client file transfer system in C. There are clients which will send or list or do some other choice (in a switch case you can see) and a server storing the files and serving a lot of clients.
Multi-thread ideology is really difficult as far as I can see. It needs too much experience instead of knowledge. I have been working on the project for more than one week and I haven't been able to get on top of the problems.
There are 4 choices: first one is lists local files of client in its directory, second one is list files which are transferred between the client and server, third reading filename from user and copy the file into server's directory.
My vital issue here is about multi-threading. I cannot connect multiple clients. I have read the code from a to z heaps of times but I really can't catch my errors and am stuck.
The other issue is that the client will end when the SIGINT is caught, but, for instance, after choosing list files when press ctrl-c it doesn't stop. Same issue for the server file as well. It is more troublesome compared to the client's catching because when server gets SIGINT, clients will be disconnected respectively from the server.
Thanks for your helps!
server.c
/*
Soner
Receive a file over a socket.
Saves it to output.tmp by default.
Interface:
./executable [<port>]
Defaults:
- output_file: output.tmp
- port: 12345
*/
#define _XOPEN_SOURCE 700
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <netdb.h> /* getprotobyname */
#include <netinet/in.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <unistd.h>
#include <pthread.h>
pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;
enum { PORTSIZE = 5 };
void* forClient(void* ptr);
void sig_handler(int signo)
{
if (signo == SIGINT)
printf("!! OUCH, CTRL - C received by server !!\n");
}
int main(int argc, char **argv) {
struct addrinfo hints, *res;
int enable = 1;
int filefd;
int server_sockfd;
unsigned short server_port = 12345u;
char portNum[PORTSIZE];
socklen_t client_len[BUFSIZ];
struct sockaddr_in client_address[BUFSIZ];
int client_sockfd[BUFSIZ];
int socket_index = 0;
pthread_t threads[BUFSIZ];
if (argc != 2) {
fprintf(stderr, "Usage ./server <port>\n");
exit(EXIT_FAILURE);
}
server_port = strtol(argv[1], NULL, 10);
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_INET; //ipv4
hints.ai_socktype = SOCK_STREAM; // tcp
hints.ai_flags = AI_PASSIVE; // fill in my IP for me
sprintf(portNum, "%d", server_port);
getaddrinfo(NULL, portNum, &hints, &res);
server_sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
if (server_sockfd == -1) {
perror("socket");
exit(EXIT_FAILURE);
}
if (setsockopt(server_sockfd, SOL_SOCKET, (SO_REUSEPORT | SO_REUSEADDR), &enable, sizeof(enable)) < 0) {
perror("setsockopt(SO_REUSEADDR) failed");
exit(EXIT_FAILURE);
}
if (bind(server_sockfd, res->ai_addr, res->ai_addrlen) == -1) {
perror("bind");
exit(EXIT_FAILURE);
}
if (listen(server_sockfd, 5) == -1) {
perror("listen");
exit(EXIT_FAILURE);
}
fprintf(stderr, "listening on port %d\n", server_port);
while (1) {
client_len[socket_index] = sizeof(client_address[socket_index]);
puts("waiting for client");
client_sockfd[socket_index] = accept(
server_sockfd,
(struct sockaddr*)&client_address[socket_index],
&client_len[socket_index]
);
if (client_sockfd[socket_index] < 0) {
perror("Cannot accept connection\n");
close(server_sockfd);
exit(EXIT_FAILURE);
}
pthread_create( &threads[socket_index], NULL, forClient, (void*)client_sockfd[socket_index]);
if(BUFSIZ == socket_index) {
socket_index = 0;
} else {
++socket_index;
}
pthread_join(threads[socket_index], NULL);
close(filefd);
close(client_sockfd[socket_index]);
}
return EXIT_SUCCESS;
}
void* forClient(void* ptr) {
int connect_socket = (int) ptr;
int filefd;
ssize_t read_return;
char buffer[BUFSIZ];
char *file_path;
char receiveFileName[BUFSIZ];
int ret = 1;
// Thread number means client's id
printf("Thread number %ld\n", pthread_self());
pthread_mutex_lock( &mutex1 );
// until stop receiving go on taking information
while (recv(connect_socket, receiveFileName, sizeof(receiveFileName), 0)) {
file_path = receiveFileName;
fprintf(stderr, "is the file name received? ? => %s\n", file_path);
filefd = open(file_path,
O_WRONLY | O_CREAT | O_TRUNC,
S_IRUSR | S_IWUSR);
if (filefd == -1) {
perror("open");
exit(EXIT_FAILURE);
}
do {
read_return = read(connect_socket, buffer, BUFSIZ);
if (read_return == -1) {
perror("read");
exit(EXIT_FAILURE);
}
if (write(filefd, buffer, read_return) == -1) {
perror("write");
exit(EXIT_FAILURE);
}
} while (read_return > 0);
}
pthread_mutex_unlock( &mutex1 );
fprintf(stderr, "Client dropped connection\n");
pthread_exit(&ret);
}
client.c
/*
Soner
Send a file over a socket.
Interface:
./executable [<sever_hostname> [<port>]]
Defaults:
- server_hostname: 127.0.0.1
- port: 12345
*/
#define _XOPEN_SOURCE 700
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <netdb.h> /* getprotobyname */
#include <netinet/in.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <unistd.h>
// NOTE/BUG: this didn't provide enough space for a 5 digit port + EOS char
#if 0
enum { PORTSIZE = 5 };
#else
enum { PORTSIZE = 6 };
#endif
void
sig_handler(int signo)
{
if (signo == SIGINT)
printf("!! OUCH, CTRL - C received on client !!\n");
}
int
main(int argc, char **argv)
{
struct addrinfo hints,
*res;
char *server_hostname = "127.0.0.1";
char file_path[BUFSIZ];
char *server_reply = NULL;
char *user_input = NULL;
char buffer[BUFSIZ];
int filefd;
int sockfd;
ssize_t read_return;
struct hostent *hostent;
unsigned short server_port = 12345;
char portNum[PORTSIZE];
char remote_file[BUFSIZ];
int select;
char *client_server_files[BUFSIZ];
int i = 0;
int j;
// char filename_to_send[BUFSIZ];
if (argc != 3) {
fprintf(stderr, "Usage ./client <ip> <port>\n");
exit(EXIT_FAILURE);
}
server_hostname = argv[1];
server_port = strtol(argv[2], NULL, 10);
/* Prepare hint (socket address input). */
hostent = gethostbyname(server_hostname);
if (hostent == NULL) {
fprintf(stderr, "error: gethostbyname(\"%s\")\n", server_hostname);
exit(EXIT_FAILURE);
}
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_INET; // ipv4
hints.ai_socktype = SOCK_STREAM; // tcp
hints.ai_flags = AI_PASSIVE; // fill in my IP for me
sprintf(portNum, "%d", server_port);
getaddrinfo(NULL, portNum, &hints, &res);
sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
if (sockfd == -1) {
perror("socket");
exit(EXIT_FAILURE);
}
/* Do the actual connection. */
if (connect(sockfd, res->ai_addr, res->ai_addrlen) == -1) {
perror("connect");
return EXIT_FAILURE;
}
while (1) {
if (signal(SIGINT, sig_handler)) {
break;
}
puts("connected to the server");
puts("-----------------");
puts("|1 - listLocal| \n|2 - listServer| \n|3 - sendFile| \n|4 - help| \n|5 - exit| ");
puts("-----------------");
while (1) {
scanf("%d", &select);
switch (select) {
case 1: // list files of client's directory
system("find . -maxdepth 1 -type f | sort");
break;
case 2: // listServer
puts("---- Files btw Server and the Client ----");
for (j = 0; j < i; ++j) {
puts(client_server_files[j]);
}
break;
case 3: // send file
memset(file_path, 0, sizeof file_path);
scanf("%s", file_path);
memset(remote_file, 0, sizeof remote_file);
// send file name to server
sprintf(remote_file, "%s", file_path);
send(sockfd, remote_file, sizeof(remote_file), 0);
filefd = open(file_path, O_RDONLY);
if (filefd == -1) {
perror("open send file");
//exit(EXIT_FAILURE);
break;
}
while (1) {
read_return = read(filefd, buffer, BUFSIZ);
if (read_return == 0)
break;
if (read_return == -1) {
perror("read");
//exit(EXIT_FAILURE);
break;
}
if (write(sockfd, buffer, read_return) == -1) {
perror("write");
//exit(EXIT_FAILURE);
break;
}
}
// add files in char pointer array
client_server_files[i++] = file_path;
close(filefd);
break;
case 5:
free(user_input);
free(server_reply);
exit(EXIT_SUCCESS);
default:
puts("Wrong selection!");
break;
}
}
}
free(user_input);
free(server_reply);
exit(EXIT_SUCCESS);
}
I fixed most of the bugs that others have mentioned.
Key points to get multithread/multiclient working:
Eliminate mutex.
Consolidate all arrays previously indexed by socket_index into a new "control" struct. main thread does a malloc for the struct, fills it in, and passes off the struct pointer to the thread.
Remove pthread_join from main thread and run all threads detached. main no longer does any close/cleanup for the client thread.
client thread now does the close/cleanup/free.
Even with all that, the server/client code still needs some work, but now, it does work with multiple simultaneous client connections which I believe was the main issue.
Note: I've answered a similar question before: executing commands via sockets with popen() Pay particular attention to the discussion of the "flag" character.
Anyway, Here's the code. I've cleaned it, annotated the bugs and fixes and wrapped the old/new code with #if 0. Note that some of the "old" code isn't purely original code, but an interim version of mine. [please pardon the gratuitous style cleanup]:
server.c:
/*
Soner
Receive a file over a socket.
Saves it to output.tmp by default.
Interface:
./executable [<port>]
Defaults:
- output_file: output.tmp
- port: 12345
*/
#define _XOPEN_SOURCE 700
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <netdb.h> /* getprotobyname */
#include <netinet/in.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <unistd.h>
#include <pthread.h>
// NOTE: this consolidates four arrays that were indexed by socket_index
struct client {
socklen_t client_len;
struct sockaddr_in client_address;
int client_sockfd;
pthread_t thread;
};
// NOTE: no longer used/needed for true multiclient
#if 0
pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;
#endif
// NOTE/BUG: this didn't provide enough space for a 5 digit port + EOS char
#if 0
enum { PORTSIZE = 5 };
#else
enum { PORTSIZE = 6 };
#endif
void *forClient(void *ptr);
void
sig_handler(int signo)
{
if (signo == SIGINT)
printf("!! OUCH, CTRL - C received by server !!\n");
}
int
main(int argc, char **argv)
{
struct addrinfo hints,
*res;
int enable = 1;
//int filefd; // NOTE: this is never initialized/used
int server_sockfd;
unsigned short server_port = 12345u;
char portNum[PORTSIZE];
// NOTE: now all client related data is malloc'ed
#if 0
int socket_index = 0;
#else
struct client *ctl;
#endif
if (argc != 2) {
fprintf(stderr, "Usage ./server <port>\n");
exit(EXIT_FAILURE);
}
server_port = strtol(argv[1], NULL, 10);
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_INET; // ipv4
hints.ai_socktype = SOCK_STREAM; // tcp
hints.ai_flags = AI_PASSIVE; // fill in my IP for me
sprintf(portNum, "%d", server_port);
getaddrinfo(NULL, portNum, &hints, &res);
server_sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
if (server_sockfd == -1) {
perror("socket");
exit(EXIT_FAILURE);
}
if (setsockopt(server_sockfd, SOL_SOCKET, (SO_REUSEPORT | SO_REUSEADDR), &enable, sizeof(enable)) < 0) {
perror("setsockopt(SO_REUSEADDR) failed");
exit(EXIT_FAILURE);
}
if (bind(server_sockfd, res->ai_addr, res->ai_addrlen) == -1) {
perror("bind");
exit(EXIT_FAILURE);
}
if (listen(server_sockfd, 5) == -1) {
perror("listen");
exit(EXIT_FAILURE);
}
fprintf(stderr, "listening on port %d\n", server_port);
// NOTE: we want the threads to run detached so we don't have to wait
// for them to do cleanup -- the thread now does its own close/cleanup
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr,1);
while (1) {
// NOTE/BUG: using a fixed list, if you actually let threads detach,
// you don't know which thread completes allowing its control struct
// to be reused
// the solution is to allocate a fresh one, fill it, pass it to the
// thread and let the _thread_ do all the closes and cleanup
#if 0
ctl = &control_list[socket_index];
#else
ctl = malloc(sizeof(struct client));
if (ctl == NULL) {
perror("malloc");
exit(EXIT_FAILURE);
}
#endif
ctl->client_len = sizeof(ctl->client_address);
puts("waiting for client");
ctl->client_sockfd = accept(server_sockfd,
(struct sockaddr *) &ctl->client_address, &ctl->client_len);
if (ctl->client_sockfd < 0) {
perror("Cannot accept connection\n");
close(server_sockfd);
exit(EXIT_FAILURE);
}
// NOTE: we're running the threads detached now and we're passing down
// extra information just in case the client loop needs it
#if 0
pthread_create(&ctl->thread, NULL, forClient, ctl);
#else
pthread_create(&ctl->thread, &attr, forClient, ctl);
#endif
#if 0
if (BUFSIZ == socket_index) {
socket_index = 0;
}
else {
++socket_index;
}
#endif
// NOTE/BUG: this is why you couldn't do multiple clients at the same
// time -- you are doing a thread join
// but you _had_ to because the main thread didn't know when a thread
// was done with the control struct without the join
#if 0
pthread_join(threads[socket_index], NULL);
close(filefd);
close(client_sockfd[socket_index]);
#endif
}
return EXIT_SUCCESS;
}
void *
forClient(void *ptr)
{
#if 0
int connect_socket = (int) ptr;
#else
struct client *ctl = ptr;
int connect_socket = ctl->client_sockfd;
#endif
int filefd;
ssize_t read_return;
char buffer[BUFSIZ];
char *file_path;
long long file_length;
char receiveFileName[BUFSIZ];
//int ret = 1;
// Thread number means client's id
printf("Thread number %ld\n", pthread_self());
// NOTE: to run parallel threads, this prevents that
#if 0
pthread_mutex_lock(&mutex1);
#endif
// until stop receiving go on taking information
while (recv(connect_socket, receiveFileName, sizeof(receiveFileName), 0)) {
// NOTE/FIX2: now we have the client send us the file length so we
// know when to stop the read loop below
file_length = strtoll(receiveFileName,&file_path,10);
if (*file_path != ',') {
fprintf(stderr,"syntax error in request -- '%s'\n",
receiveFileName);
exit(EXIT_FAILURE);
}
file_path += 1;
fprintf(stderr, "is the file name received? ? => %s [%lld bytes]\n",
file_path,file_length);
// NOTE: if you want to see _why_ sending the length is necessary,
// uncomment this line and the "unable to send two files" bug will
// reappear
//file_length = 1LL << 62;
filefd = open(file_path,
O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
if (filefd == -1) {
perror("open");
exit(EXIT_FAILURE);
}
// NOTE/BUG2/FIX: now we only read up to what we're told to read
// previously, we would keep trying to read, so on the _second_
// send, our read call here would get the data that _should_ have
// gone into the recv above
// in other words, we'd lose synchronization with what the client
// was sending us [and we'd put the second filename into the first
// file as data at the bottom]
for (; file_length > 0; file_length -= read_return) {
read_return = BUFSIZ;
if (read_return > file_length)
read_return = file_length;
read_return = read(connect_socket, buffer, read_return);
if (read_return == -1) {
perror("read");
exit(EXIT_FAILURE);
}
if (read_return == 0)
break;
if (write(filefd, buffer, read_return) == -1) {
perror("write");
exit(EXIT_FAILURE);
}
}
fprintf(stderr,"file complete\n");
// NOTE/BUG: filefd was never closed
#if 1
close(filefd);
#endif
}
#if 0
pthread_mutex_unlock(&mutex1);
#endif
fprintf(stderr, "Client dropped connection\n");
// NOTE: do all client related cleanup here
// previously, the main thread was doing the close, which is why it had
// to do the pthread_join
close(connect_socket);
free(ctl);
// NOTE: this needs a void * value like below
#if 0
pthread_exit(&ret);
#endif
return (void *) 0;
}
client.c:
/*
Soner
Send a file over a socket.
Interface:
./executable [<sever_hostname> [<port>]]
Defaults:
- server_hostname: 127.0.0.1
- port: 12345
*/
#define _XOPEN_SOURCE 700
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <netdb.h> /* getprotobyname */
#include <netinet/in.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <unistd.h>
// NOTE/BUG: this didn't provide enough space for a 5 digit port + EOS char
#if 0
enum { PORTSIZE = 5 };
#else
enum { PORTSIZE = 6 };
#endif
// NOTE2: the "volatile" attribute here is critical to proper operation
volatile int signo_taken;
// NOTE/BUG2: don't use BUFSIZ when you really want something else
#define MAXFILES 1000
void
sig_handler(int signo)
{
// NOTE/BUG2/FIX: doing printf within a signal handler is _not_ [AFAIK] a
// safe thing to do because it can foul up the internal structure data of
// stdout if the base task was doing printf/puts and the signal occurred
// in the middle -- there are a number of other restrictions, such as
// _no_ malloc, etc.
// so, just alert the base layer and let it handle things when it's in a
// "safe" state to do so ...
signo_taken = signo;
}
int
main(int argc, char **argv)
{
struct addrinfo hints,
*res;
char *server_hostname = "127.0.0.1";
char file_path[BUFSIZ];
char *server_reply = NULL;
char *user_input = NULL;
char buffer[BUFSIZ];
int filefd;
int sockfd;
struct stat st;
ssize_t read_return;
struct hostent *hostent;
unsigned short server_port = 12345;
char portNum[PORTSIZE];
char remote_file[BUFSIZ];
int select;
char *client_server_files[MAXFILES];
int i = 0;
int j;
// char filename_to_send[BUFSIZ];
if (argc != 3) {
fprintf(stderr, "Usage ./client <ip> <port>\n");
exit(EXIT_FAILURE);
}
server_hostname = argv[1];
server_port = strtol(argv[2], NULL, 10);
/* Prepare hint (socket address input). */
hostent = gethostbyname(server_hostname);
if (hostent == NULL) {
fprintf(stderr, "error: gethostbyname(\"%s\")\n", server_hostname);
exit(EXIT_FAILURE);
}
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_INET; // ipv4
hints.ai_socktype = SOCK_STREAM; // tcp
hints.ai_flags = AI_PASSIVE; // fill in my IP for me
sprintf(portNum, "%d", server_port);
getaddrinfo(NULL, portNum, &hints, &res);
sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
if (sockfd == -1) {
perror("socket");
exit(EXIT_FAILURE);
}
/* Do the actual connection. */
if (connect(sockfd, res->ai_addr, res->ai_addrlen) == -1) {
perror("connect");
return EXIT_FAILURE;
}
// NOTE/FIX2: this only needs to be done once, since the desired action is
// to [cleanly] stop the program
signal(SIGINT, sig_handler);
// NOTES:
// (1) instead of using signo_taken as is done, below there are alternate
// ways to handle signals with sigsetjmp and siglongjmp
// (2) but the main reason to _not_ do this is to prevent the handler
// from messing up a file transfer
while (! signo_taken) {
puts("connected to the server");
#if 0
puts("-----------------");
puts("|1 - listLocal| \n|2 - listServer| \n|3 - sendFile| \n|4 - help| \n|5 - exit| ");
puts("-----------------");
#endif
while (! signo_taken) {
// NOTE: not a bug, but it helps the user to output the menu each
// time
#if 1
puts("-----------------");
puts("|1 - listLocal| \n|2 - listServer| \n|3 - sendFile| \n|4 - help| \n|5 - exit| ");
puts("-----------------");
#endif
scanf("%d", &select);
// NOTE: we should check this after _any_ call that requests user
// input (e.g. scanf, fgets(...,stdin), etc.)
if (signo_taken)
break;
switch (select) {
case 1: // list files of client's directory
system("find . -maxdepth 1 -type f | sort");
break;
case 2: // listServer
puts("---- Files btw Server and the Client ----");
for (j = 0; j < i; ++j) {
puts(client_server_files[j]);
}
break;
case 3: // send file
fputs("Enter filename: ",stdout);
fflush(stdout);
memset(file_path, 0, sizeof file_path);
scanf("%s", file_path);
if (signo_taken)
break;
// NOTE/FIX: check the file _before_ sending request to server
// and we [now] want to know the file length so we can send
// that to the server so it will know when to stop receiving
#if 1
filefd = open(file_path, O_RDONLY);
if (filefd == -1) {
perror("open send file");
// exit(EXIT_FAILURE);
break;
}
// get the file's byte length
if (fstat(filefd,&st) < 0) {
perror("stat send file");
// exit(EXIT_FAILURE);
close(filefd);
break;
}
#endif
// send file name to server
memset(remote_file, 0, sizeof(remote_file));
#if 0
sprintf(remote_file, "%s", file_path);
#else
sprintf(remote_file, "%lld,%s",
(long long) st.st_size,file_path);
#endif
send(sockfd, remote_file, sizeof(remote_file), 0);
// NOTE/BUG2: this should be done above to _not_ confuse server
#if 0
filefd = open(file_path, O_RDONLY);
if (filefd == -1) {
perror("open send file");
// exit(EXIT_FAILURE);
break;
}
#endif
while (1) {
read_return = read(filefd, buffer, BUFSIZ);
if (read_return == 0)
break;
if (read_return == -1) {
perror("read");
// exit(EXIT_FAILURE);
break;
}
if (write(sockfd, buffer, read_return) == -1) {
perror("write");
// exit(EXIT_FAILURE);
break;
}
}
close(filefd);
// add files in char pointer array
// NOTE/BUG2: file_path gets overwritten, so we must save it
// here
#if 0
client_server_files[i++] = file_path;
#else
if (i < MAXFILES)
client_server_files[i++] = strdup(file_path);
#endif
puts("file complete");
break;
case 5:
free(user_input);
free(server_reply);
exit(EXIT_SUCCESS);
break;
default:
puts("Wrong selection!");
break;
}
}
}
// NOTE/FIX2: we output this here when it's save to do so
if (signo_taken)
printf("!! OUCH, CTRL - C received on client !!\n");
free(user_input);
free(server_reply);
exit(EXIT_SUCCESS);
}
UPDATE:
I have solved my connection-interruption problem but signal is still occurring. I left two problems more times file sending and signal handling
I have reworked the client signal handling so that it works as expected [which is to print the message and stop the client].
I have also fixed the problem where only one file could be sent. To understand this, consider the actions of both client and server.
To send a file, client prompts for filename, does a send call with the filename in it. It then opens the file and does a read/write loop to send the file data to the server [and then closes the file descriptor].
To receive a file, server does a recv call to get the filename. It then opens the file [for output] and does a read/write to write the data from the socket to the file [and then closes the file descriptor].
Here is the problem: The termination condition for the server's read/write loop is to wait until the read(connect_socket,...) call returns 0. But, it will not return zero [unless the socket has been closed].
So, now the client does a send call to send the second filename. But, the data for this, instead of going into the server's recv call, will merely be part of the read buffer. That is, the second filename will just be appended to the first file as data.
The solution is to have the client tell the server what the file size is. So, instead of the client doing a send of filename, it now does a send of filesize,filename
The server will now decode this filesize and split off the filename in the recv buffer. Now, the server's read/write loop will maintain a count of how many bytes still need to be read and the loop stops when the remaining count hits zero.
There were one or two other minor bugs. I've updated both client.c and server.c with the bug fixes and annotations
I've made a message queue for my fileserver (runs on linux) and it all seems to go well when I upload (from windows client) a file to the the server through the client. Once the file is uploaded though I get all these vague symbols on the serverside.
I've got the following code on the client side
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <stddef.h>
#include "mailbox.h"
#define MAXCLIENTS 5
#define PORTNR 5002
#define MAXUSERS 1024
/*
int inet_aton(const char *cp, struct in_addr *inp);
char *inet_ntoa(struct in_addr in);
void *memset(void *s, int c, size_t n);
int close(int fd);
*/
//Prototyping van de functies
void *childThread(void *ad);
void uploadFile(int nsockfd);
void downloadFile(int nsockfd);
void establishConnection();
int login(char *username, char *password);
int get_queue_ds( int qid, struct msqid_ds *qbuf);
int change_queue_mode(int qid, char *mode);
//Upload files= 0, Download files= 1
int serverState = 0;
int numberLoggedInUsers = 0;
struct sockaddr_in client; // Struct for Server addr
struct message req;
struct msqid_ds mq_id = {0};
int clientUpload;
ssize_t msgLen;
char *username;
char *password;
int main(int argc, char** argv) {
// create message queue key
key_t key;
if((key = ftok("/home/MtFS/Iteraties/ftokDing", 13)) < 0) {
perror("ftok");
exit(1);
}
// create queue, if not succesfull, remove old queue
// and try to make a new one.
while ((clientUpload = msgget(key, 0666 | IPC_CREAT| IPC_EXCL)) < 0) { //| S_IRGRP | S_IWUSR
perror("msgget");
// delete message queue if it exists
if (msgctl(clientUpload, IPC_RMID, &mq_id) == -1) {
perror("msgctl1");
exit(1);
}
}
change_queue_mode(clientUpload, "0666");
/*
if (msgctl(clientUpload, IPC_STAT, &mq_id) == -1) {
perror("msgctl2");
exit(1);
}
if (msgctl(clientUpload, IPC_SET, &mq_id) == -1) {
perror("msgctl3");
exit(1);
}
*/
establishConnection();
return 0;
}
int get_queue_ds(int qid, struct msqid_ds *qbuf) {
if (msgctl(qid, IPC_STAT, qbuf) == -1) {
perror("msgctl IPC_STAT");
exit(1);
}
return 0;
}
int change_queue_mode(int qid, char *mode) {
struct msqid_ds tmpbuf;
/* Retrieve a current copy of the internal data structure */
get_queue_ds(qid, &tmpbuf);
/* Change the permissions using an old trick */
sscanf(mode, "%ho", &tmpbuf.msg_perm.mode);
/* Update the internal data structure */
if (msgctl(qid, IPC_SET, &tmpbuf) == -1) {
perror("msgctl IPC_SET");
exit(1);
}
return (0);
}
void establishConnection() {
pthread_t child; //Thread ID of created thread
int sockfd; //Integer for socket
int nsockfd; //Integer for client socket
socklen_t sizeAddr; //Length of socket
struct sockaddr_in addr; //Struct for client addr
int optValue = 1; //Int for setsockoptions
char ipAdres[32] = "192.168.80.2"; //IP-adres of server
sizeAddr = sizeof (struct sockaddr_in);
// create socket and errorhandling if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("[socket()]");
exit(1);
} else {
printf("================================================================\n\n");
printf("Socket created succesfully.\n\n");
}
// Fill socket with portno and ip address
addr.sin_family = AF_INET; // Protocol Family
addr.sin_port = htons(PORTNR); // Portnumber
inet_aton(ipAdres, &addr.sin_addr); // Local IP- adres
bzero(&(addr.sin_zero), 8); // empty rest of struct
// int setsockopt (int fd, int level, int optname, const void *optval, socklen_t optlen)
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &optValue, sizeof (int)) == -1) {
perror("[setsockopt()]");
exit(1);
}
// Fil socket with portnr and ip adress, also implemented error handling
if (bind(sockfd, (struct sockaddr*) &addr, sizeof (struct sockaddr)) == -1) {
perror("[bind()]");
exit(1);
} else {
printf("================================================================\n\n");
printf("Portnr %d is succesfully connected %s to.\n\n", PORTNR, ipAdres);
}
// Listen to incoming connections and errorhandling
if (listen(sockfd, MAXCLIENTS) == -1) {
perror("[listen()]");
exit(1);
} else {
printf("================================================================\n\n");
printf("Listen to port %d successfull.\n\n", PORTNR);
}
//Connectionloop to process connection requests from clients
while (1) {
//Accept incoming clients with error handling.
if ((nsockfd = accept(sockfd, (struct sockaddr *) &client, &sizeAddr)) == -1) {
perror("[accept()]");
exit(1);
} else {
//create child thread
pthread_create(&child, NULL, childThread, (void *) nsockfd);
/*
// wait untill other child is ready
pthread_join(child, &status);
*/
}
}
}
void *childThread(void *nsockfd) {
int sizeReceivedFile = 0;
char receiveBuffer[PACKETSIZE]; //Buffer voor de ontvangen bestanden
//char sendBuffer[PACKETSIZE]; //Buffer voor de te zenden bestanden
//int sizeSendFile = 0; //Grootte van het te zenden bestand
//char yolocol[PACKETSIZE];
char *clientRequest; //Char pointer voor het type request client, permissie en bestandsnaam
int loginStatus = 0; // 0 = uitgelogd, 1 = ingelogd
char *loggedInAs;
printf("================================================================\n\n");
printf("Connected with a client on IP-Adres: %s.\n\n", inet_ntoa(client.sin_addr));
bzero(receiveBuffer, PACKETSIZE);
while ((sizeReceivedFile = recv((int) nsockfd, receiveBuffer, PACKETSIZE, 0)) > 0) {
// receive from client
printf("Ontvangen buffer: %s\n",receiveBuffer);
if (sizeReceivedFile == 0) {
break;
}
// flags
// retreive flag with strtok
clientRequest = strtok(receiveBuffer, "#");
printf("packet type: %s\n", clientRequest);
// 2 = list
// 3 = download
// 4 = upload
// 5 = login
// 6 = logout
if (strcmp(clientRequest, "2") == 0) {
printf("execute list on current directory!\n");
} else if (strcmp(clientRequest, "3") == 0) {
downloadFile((int) nsockfd);
} else if (strcmp(clientRequest, "4") == 0) {
uploadFile((int) nsockfd);
} else if (strcmp(clientRequest, "5") == 0){
username = strtok(NULL,"#");
password = strtok(NULL,"#");
printf("Username = %s \n password = %s \n",username,password);
int test;
if((test= login(username,password))== 1){
printf("login success, %i\n", test);
loginStatus = 1;
}
else{
printf("Inloggen mislukt, %i\n", test);
loginStatus = 0;
}
} else if (strcmp(clientRequest, "6")== 0) {
loginStatus = 0;
printf("%s logged out\n", loggedInAs);
loggedInAs = "";
}
}
return 0;
}
void uploadFile(int nsockfd) {
/*
printf("execute download!\n");
fileToDownload = strtok(NULL,"#");
printf("%s",fileToDownload);
int sizeReceivedFile = 0;
// if relcv() returns 0 then the connection is gone
while (sizeReceivedFile != 0) {
//Upload of files
if (serverState == 0) {
sizeReceivedFile = recv((int) nsockfd, req.pakket.buffer, PACKETSIZE, 0);
if (sizeReceivedFile < 0) {
perror("[receive()]");
exit(0);
} else if (sizeReceivedFile == 0) {
printf("The client has dropped the connection \n");
close((int) nsockfd);
pthread_exit(NULL);
}
// put the packet in the mailbox
req.mtype = RESP_MT_DATA; // has to be positive
req.pakket.clientID = clientUpload;
if (msgsnd(clientUpload, &req, PACKETSIZE, 0) == -1) {
perror("msgsnd");
}
}
}
req.mtype = RESP_MT_END;
msgsnd(clientUpload, &req, 0, 0);
close((int) nsockfd);
printf("================================================================\n\n");
printf("Connection with client has been lost. Server is waiting for new clients clients...\n\n");
}
void downloadFile(int nsockfd) {
/*
printf("execute download!\n");
fileToDownload = strtok(NULL,"#");
printf("%s",fileToDownload);
*/
char sendBuffer[PACKETSIZE];
int sizeSendFile = 0;
if (send((int) nsockfd, sendBuffer, sizeSendFile, 0) < 0) {
perror("[send()]");
//exit(1);
}
bzero(sendBuffer, PACKETSIZE);
}
And this is the server side. I made one process for handling the connection, which transfers all incoming packets that say 'upload' in one of my custom made protocol flags to a message queue. This is the code:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <stddef.h>
#include "mailbox.h" // self made header file
#define MAXCLIENTS 5
#define PORT 5002
#define MAXUSERS 1024
//Prototyping
void *childThread(void *ad);
void uploadFile(int nSockfd);
void buildConnection();
int get_queue_ds( int qid, struct msqid_ds *qbuf);
int change_queue_mode(int qid, char *mode);
// Upload files= 0, Download files= 1
int serverState = 0;
struct sockaddr_in client;
struct bericht req;
struct msqid_ds mq_id = {0};
int messageQueue;
ssize_t msgLen;
int main(int argc, char** argv) {
// message queue key aanmaken
key_t key;
if((key = ftok("/home/file", 13)) < 0) {
perror("ftok");
exit(1);
}
// queue aanmaken, als dit niet lukt de eventueel oude queue verwijderen
// en queue opnieuw proberen aan te maken.
while ((messageQueue = msgget(key, 0666 | IPC_CREAT| IPC_EXCL)) < 0) {
perror("msgget");
// message queue verwijderen als deze al bestaat
if (msgctl(messageQueue, IPC_RMID, &mq_id) == -1) {
perror("msgctl1");
exit(1);
}
}
change_queue_mode(messageQueue, "0666");
buildConnection();
return 0;
}
int get_queue_ds(int qid, struct msqid_ds *qbuf) {
if (msgctl(qid, IPC_STAT, qbuf) == -1) {
perror("msgctl IPC_STAT");
exit(1);
}
return 0;
}
int change_queue_mode(int qid, char *mode) {
struct msqid_ds tmpbuf;
// Retrieve a current copy of the internal data structure
get_queue_ds(qid, &tmpbuf);
// Change the permissions using an old trick
sscanf(mode, "%ho", &tmpbuf.msg_perm.mode);
// Update the internal data structure
if (msgctl(qid, IPC_SET, &tmpbuf) == -1) {
perror("msgctl IPC_SET");
exit(1);
}
return (0);
}
void buildConnection() {
pthread_t child;
int sockfd;
int nSockfd;
socklen_t sockaddrSize;
struct sockaddr_in addr;
int optValue = 1;
char ipAdres[32] = "192.168.80.2";
sockaddrSize = sizeof (struct sockaddr_in);
// create socket
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("[socket()]");
exit(1);
} else {
printf("================================================================\n\n");
printf("Socket is succesfully created.\n\n");
}
// fill dat socket
addr.sin_family = AF_INET;
addr.sin_port = htons(PORT);
inet_aton(ipAdres, &addr.sin_addr);
bzero(&(addr.sin_zero), 8);
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &optValue, sizeof (int)) == -1) {
perror("[setsockopt()]");
exit(1);
}
if (bind(sockfd, (struct sockaddr*) &addr, sizeof (struct sockaddr)) == -1) {
perror("[bind()]");
exit(1);
} else {
printf("================================================================\n\n");
printf("bind succesful");
}
if (listen(sockfd, MAXCLIENTS) == -1) {
perror("[listen()]");
exit(1);
} else {
printf("================================================================\n\n");
printf("Listening on port %d\n\n", PORT);
}
// Connection loop
while (1) {
// accept incoming clients
if ((nSockfd = accept(sockfd, (struct sockaddr *) &client, &sockaddrSize)) == -1) {
perror("[accept()]");
exit(1);
} else {
pthread_create(&child, NULL, childThread, (void *) nSockfd);
}
}
}
void *childThread(void *nSockfd) {
int sizeOfRecvFile = 0;
char recvBuffer[PACKETSIZE];
char *clientCommand; // request type
printf("================================================================\n\n");
printf("connected to client with IP: %s.\n\n", inet_ntoa(client.sin_addr));
bzero(recvBuffer, PACKETSIZE);
// get dem datas
while ((sizeOfRecvFile = recv((int) nSockfd, recvBuffer, PACKETSIZE, 0)) > 0) {
if (sizeOfRecvFile == 0) {
break;
}
printf("received buffer: %s\n", recvBuffer);
// handle protocol flag
// chop protocol into pieces to check packet data and flags
clientCommand = strtok(recvBuffer, "#");
printf("packet type: %s\n", clientCommand);
// if clientCommand == 4
// incoming file!
if (strcmp(clientCommand, "4") == 0) {
uploadFile((int) nSockfd);
}
}
return 0;
}
void uploadFile(int nSockfd) {
int sizeOfRecvFile = 0;
// if recv() is 0 close connection
while (sizeOfRecvFile != 0) {
if (serverStaat == 0) {
sizeOfRecvFile = recv((int) nSockfd, req.pakket.buffer, PACKETSIZE, 0);
if (sizeOfRecvFile < 0) {
perror("[receive()]");
exit(0);
} else if (sizeOfRecvFile == 0) {
printf("Client disconnected\n");
close((int) nSockfd);
pthread_exit(NULL);
}
// send packet to message queue
req.mtype = RESP_MT_DATA;
req.pakket.clientID = messageQueue;
if (msgsnd(messageQueue, &req, PACKETSIZE, 0) == -1) {
perror("msgsnd");
}
}
}
req.mtype = RESP_MT_END;
msgsnd(messageQueue, &req, 0, 0);
close((int) nSockfd);
printf("================================================================\n\n");
printf("Disconnected, now waiting for other clients...\n\n");
}
The above program uses a custom made header file:
#include <sys/types.h>
#include <sys/msg.h>
#include <sys/stat.h>
#include <stddef.h>
#include <limits.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/wait.h>
#define PACKETSIZE 65535
struct message {
long mtype;
struct packet {
int clientID;
char buffer[PACKETSIZE];
} packet;
};
#define REQ_MSG_SIZE (offsetof(struct message.pakket, buffer) - \
offsetof(struct message.pakket, clientID) - PACKETSIZE)
struct responseMsg { // Responses (server to client)
long mtype; // One of RESP_MT_* values below
char data[PACKETSIZE]; // File content / response message
};
// Types for response messages sent from server to client
#define RESP_MT_FAILURE 1 // File couldn't be opened
#define RESP_MT_DATA 2 // Message contains file data
#define RESP_MT_END 3 // File data complete
I also made a process which writes the uploaded files to the hdd. This process gets data from the message queue that was created in the connection process. The code:
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/wait.h>
#include <sys/socket.h>
#include <signal.h>
#include <ctype.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
#include "/home/CommProces/mailbox.h"
#define POORTNR 5002
#define MAXCLIENTS 5
// prototyping
void writeFiles();
struct message resp;
int uploadMessage;
ssize_t msgLen;
int main () {
key_t key;
if(key = ftok("/home/CommProces/ftokDing", 13) < 0) {
perror("ftok");
exit(1);
}
uploadMessage = msgget(key, 0666);
if (uploadMessage == -1) {
perror("msgget");
exit(1);
}
while(1) {
writeFiles();
}
}
void writeFiles() {
char recvBuffer[PACKETSIZE];
char *rights, *pathname, *filename, *temp;
char *pathOfRecvFile; // received files will go here
FILE* theFile;
bzero(recvBuffer, PACKETSIZE);
int numMsgs, totBytes;
int sizeOfRecvFile = 0;
int nBytesToDisk = 0;
totBytes = msgLen; // Count first message
for (numMsgs = 1; resp.mtype == RESP_MT_DATA; numMsgs++) {
msgLen = msgrcv(uploadMessage, &resp, PACKETSIZE, 0, 0);
if (msgLen == -1) {
perror("msgrcv");
totBytes += msgLen;
}
*recvBuffer = *resp.pakket.buffer;
//temp = strtok(recvBuffer,"#");
rights = strtok(NULL,"#");
if(strcmp(rights, "private") == 0) {
temp = strtok(NULL,"#");
pathname = strcat("/home/MtFS/UploadedFiles/private/", temp);
} else {
pathname = "/home/MtFS/UploadedFiles/public";
}
filename = strcat("/", strtok(NULL,"#"));
pathOfRecvFile = strcat(filename, pathname);
theFile = fopen(pathOfRecvFile, "wb");
if(theFile == NULL) {
printf("[Open_File] unable to create file %s\n", pathOfRecvFile);
} else {
nBytesToDisk = fwrite(recvBuffer, sizeof(char), sizeOfRecvFile, theFile);
if(nBytesToDisk < sizeOfRecvFile) {
perror("fwrite");
}
printf("=============================================================================================================================\n\n");
printf("Files received and placed on HDD\n\n");
bzero(recvBuffer, PACKETSIZE);
}
if (resp.mtype == RESP_MT_FAILURE) {
printf("mtype = fail");
} else if(resp.mtype == RESP_MT_END) {
printf("mtype = end of data");
fclose(theFile);
}
}
}
I've been sifting through breakpoints with the debugger but I can't lay my finger on what's causing the problem :(
For starters, the 3rd parameter to msgrcv() gives the size of the message's payload.
So this line
msgLen = msgrcv(uploadMessage, &resp, PACKETSIZE, 0, 0);
should be
msgLen = msgrcv(uploadMessage, &resp, sizeof(resp)-sizeof(resp.mtype), 0, 0);
or
msgLen = msgrcv(uploadMessage, &resp, sizeof(resp.packet), 0, 0);
Also calling strtok() with the 1st argument set to NULL, does not make sense. It initialy needs to be called with the 1st agrment pointing to some 0 -terminated char-array.
Also^2: Trying to concatenate to a string literal uinsg strcat() like here:
pathname = strcat("/home/MtFS/UploadedFiles/private/", temp);
invokes undefined behaviour.
To fix this make pathname a buffer, instead of a pointer:
char pathname[PATHMAX] = "";
...
if(strcmp(rights, "private") == 0) {
temp = strtok(NULL,"#");
strcpy(pathname, "/home/MtFS/UploadedFiles/private/");
strcat(pathname, temp);
} else {
strcpy(pathname, "/home/MtFS/UploadedFiles/public");
}
The code you posted is describing a non-trivial system, involving a tcp-to-mq proxy (the client) and a mq-server. I strongly advise to debug those compoments separately.