Cannot print code received by client using sockets in C - c

I don know why i can't print the information saved into my client's buffer. Firstly, the code i'm transfering from server to client is the source code of google main page. I've saved this code in a html file and the size of the whole file is 198357 bytes.
For this, i used a buffer of 1024 bytes and i've passed all the data inside loops.
I've been checking using prints the number of bytes passed by the server and received by client and both are equal to the number of bytes of the file, so the transferation is well done.
But when i try to print this data saved into the buffer it starts giving me problems.
server.c
#include<sys/socket.h>
#include<netinet/in.h>
#include<sys/types.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
int main(void)
{
struct sockaddr_in serverAddress;
serverAddress.sin_family = AF_INET;
serverAddress.sin_addr.s_addr=INADDR_ANY;
serverAddress.sin_port = htons(9999);
int server = socket(AF_INET,SOCK_STREAM,0);
if(server == -1)
{
perror("Cannot open the socket");
exit(1);
}
int active = 1;
setsockopt(server, SOL_SOCKET, SO_REUSEADDR, &active, sizeof(active));
if(bind(server, (void*)&serverAddress, sizeof(serverAddress)) !=0)
{
perror("Fail bind");
exit(1);
}
else
{
printf("success\n");
}
printf("I'm listening\n");
listen(server, SOMAXCONN);
//----------------------------------------------------
while(1)
{
struct sockaddr_in clientAddress;
unsigned int addressSize;
int client = accept(server, (struct sockaddr*)&clientAddress, &addressSize);
int child = fork();
if(child==0) //in case we stablished a connection we have to create a child and then transfer the file inside of it
{
int file = open("google.html",O_RDONLY); //open file
if(file <0)
{
perror("Empty file!\n");
return 1;
}
while(1) //Iterate until function read cannot read more bytes
{
unsigned char buffer[1024]={0};
int read_bytes = read(file,buffer,sizeof(buffer));
if(read_bytes==0)
{
printf("Transfer!\n");
break;
}
while(read_bytes>0) //Write on the client the reading bytes
{
int written_bytes;
written_bytes = write(client, buffer, read_bytes);
//printf("%d\n",written_bytes); //print to check how many bytes are passed to the client (1024)
read_bytes -= written_bytes; //breaks loop
}
}
}
close(server);
shutdown(server, SHUT_RDWR);
sleep(1);
break;
}
return 0;
}
client.c
#include<sys/socket.h>
#include<netinet/in.h>
#include<sys/types.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
int main(int argc, char* argv)
{
if(argc ==2) //you've got to received as an argument the IP of the server, i haven't implemented it yet!
{
int client = socket(AF_INET,SOCK_STREAM,0);
char recvBuffer[1024];
int n=0, s;
if(client <0)
{
printf("Cannot open the socket\n");
exit(1);
}
struct sockaddr_in serverAddress;
serverAddress.sin_family = AF_INET;
serverAddress.sin_addr.s_addr=INADDR_ANY;
serverAddress.sin_port = htons(9999);
if(connect(client, (void*)&serverAddress, sizeof(serverAddress)) !=0)
{
perror("Cannot be connected");
return 1;
}
printf("Connecting!");
char buffer2[1024];
while((n=read(client, recvBuffer,sizeof(recvBuffer)-1))>0)
{
//printf("%d\n",n); //i used to check the num of bytes passed by this and everything it's correct
recvBuffer[n] =0;
printf("%s",recvBuffer); //error, the transferation goes wrong here
}
if(n==0)
{
shutdown(client, SHUT_RD);
close(client);
}
else if(n<0)
{
perror("Read error\n");
return 1;
}
}
return 0;
}

Related

C Program Attempting to send data, from serveride to client via tcp causing immediate crash

As the title stated - any atempts made by the serverside to send data back to the client result in an imediate crash (segmentation fault). This is a simple tcp chat app - and I am only looking to send strings bidirectionaly between client and server.
Server side below - the chat() function handles communication , after calling fgets , inputting my string , and attempting to send the data - I get an immediate (segmentation fault) and crash.
#include <stdio.h>
#include <netdb.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <ifaddrs.h>
#define SA struct sockaddr
int chat(int sockfd, int port) {
for (;;) {
char *buffer_send;
char *buffer_recv;
recv(sockfd, buffer_recv, port , 0);
printf("%s", buffer_recv);
printf(":"); fgets(buffer_send, 512, stdin);
char* exit_func;
exit_func = strstr(buffer_send, "exit");
if (exit_func = strstr(buffer_send, "exit")) {
close(sockfd);
return 0;
} else {
send(sockfd, buffer_send, 512, 0);
}
}
}
int main () {
int server_socket, new_socket, c;
struct sockaddr_in socket_address, client;
server_socket = socket(AF_INET, SOCK_STREAM, 0);
if (server_socket == -1) {
printf("socket creation failed! \n");
return 1;
} printf("socket created! \n");
socket_address.sin_addr.s_addr = inet_addr("192.168.0.10");
socket_address.sin_family = AF_INET;
socket_address.sin_port = (8003);
if( bind(server_socket,(struct sockaddr *)&socket_address , sizeof(socket_address)) < 0) {
printf("bind failed! \n");
return 1;
} printf("bind done! \n");
listen(server_socket , 3);
printf("Waiting for incoming connections...\n");
c = sizeof(struct sockaddr_in);
new_socket = accept(server_socket, (struct sockaddr *)&client, (socklen_t*)&c);
if (new_socket<0) {
printf("accept failed\n");
return 1;
} printf("connection accepted!\n");
chat(new_socket, socket_address.sin_port);
return 0;
}
however the same way of sending data on my client seems to work fine (without crashing while trying to send data):
#include <stdio.h>
#include <netdb.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <ifaddrs.h>
int chat(int sockfd, int port) {
for (;;) {
char *buffer_send;
char *buffer_recv;
printf(":"); fgets(buffer_send, 512, stdin);
char* exit_func;
exit_func = strstr(buffer_send, "exit");
if (exit_func = strstr(buffer_send, "exit")) {
close(sockfd);
return 0;
} else {
send(sockfd, buffer_send, 512, 0);
}
recv(sockfd, buffer_recv, port , 0);
printf("%s", buffer_recv);
}
}
int main () {
int target_socket;
struct sockaddr_in target_server;
target_socket = socket(AF_INET, SOCK_STREAM, 0);
if (target_socket == -1) {
printf("socket creation failed!\n");
return 1;
} printf("socket created!\n");
target_server.sin_addr.s_addr = inet_addr("192.168.0.10");
target_server.sin_family = AF_INET;
target_server.sin_port = (8003);
if (connect(target_socket , (struct sockaddr *)&target_server , sizeof(target_server)) < 0) {
printf("connection failed!\n");
return 1;
} printf("connected!\n");
chat(target_socket, target_server.sin_port);
return 0;
}
You did not allocated the room for incoming messages, the same for the buffer you want to send. I expect to do some char buffer_send[512 + 1] = {}; and char buffer_recv[512 + 1] = {}; to make some place for the message content.
The + 1 is added for the extra safety, to not overwrite the NULL terminator when the message received is large enough to fill the entire allocated buffer.

Recv() function messing up other parts of my code

I am trying to execute cat|grep using a client server set-up, works as follows: client sends word to search for using grep, server executes cat|grep, sends results to client but the recv() function seems to be messing up with my code.
What's the problem?
Adding the recv() function makes other parts of my code not working, every puts() works until puts("test5"); which is where my code is stuck in the execution, putting the recv() function as a comment makes the code run fine.
Till now I am not using the word I send from the client in any way so the problem must be with the receive function itself, it's not giving an error and when I print the content I send it works fine.
Here is the relevant client part:
#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include<errno.h>
#define PORT 8080
int main(int argc, char const *argv[])
{
int sock = 0, valread;
struct sockaddr_in serv_addr;
int buffer[1024];
char buffer2[1024]={0};
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
printf("\n Socket creation error \n");
return -1;
}
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(PORT);
if(inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr)<=0)
{
perror("Invalid address \n");
return -1;
}
if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
{
perror("Connection Failed \n");
return -1;
}
int i, array[argc], countsize=0;
if(argc>=2)
{
for(i=1; i<argc; i++)
{
int number=atoi(argv[i]);
array[i-1]=number;
countsize++;
}
if(send(sock, array, countsize*sizeof(int), 0)<0)
{
printf("Error in send! %s\n", strerror(errno));
return -1;
}
if(argc>=2)
{
int i=0;
for(int i=0; i<argc; i++)
{
if(atoi(argv[i])==6)
{
puts("Please enter the name/word you want to search for in the history file: ");
char word[30];
fgets(word, 30, stdin);
if(send(sock, &word , 30, 0)<0)
printf("Error in send! %s\n", strerror(errno));
valread = read( sock , buffer2, 1024);
puts("The result cat|grep is:");
printf("%s\n", buffer2);
}
}
}
}
return 0;
}
Here is the server's main method:
#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <string.h>
#include<errno.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdbool.h>
#include <sys/wait.h>
#include<time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <pthread.h>
#include <arpa/inet.h>
#define PORT 8080
void *catgrep(void *);
int main()
{
int server_fd, new_socket;
struct sockaddr_in address;
int opt = 1;
int addrlen = sizeof(address);
char buffer2[1024]={0};
if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0)
{
perror("socket failed");
exit(EXIT_FAILURE);
}
if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR , &opt, sizeof(opt)))
{
perror("setsockopt");
exit(EXIT_FAILURE);
}
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons( PORT );
if (bind(server_fd, (struct sockaddr *)&address, sizeof(address))<0)
{
perror("bind failed");
exit(EXIT_FAILURE);
}
while (1)
{
if (listen(server_fd, 20) < 0)
{
perror("listen");
exit(EXIT_FAILURE);
}
if ((new_socket = accept(server_fd, (struct sockaddr *)&address,(socklen_t*)&addrlen))<0)
{
perror("accept");
exit(EXIT_FAILURE);
}
int arguments[10]={0};
int n = recv(new_socket, arguments ,1024*sizeof(int),0);
int j;
int argumentsize=n/sizeof(int);
for(j=0; j<argumentsize;j++)
{
if(arguments[j]==6)
{
pthread_t th5;
pthread_attr_t attr5;
pthread_attr_init(&attr5);
if(pthread_create(&th5,&attr5, catgrep,&new_socket)!=0)
{
printf("Error in pthread_create %s\n", strerror(errno));
return -1;
}
pthread_join(th5, NULL);
return -1;
}
}
close(new_socket);
}
close(server_fd);
return 1;
}
Here is my catgrep() method:
void *catgrep(void * param)
{
int *sock = (int*) param;
int new_sock = *sock;
int fd[2];
pipe(fd);
pid_t pid = fork();
char word[30];
recv(new_sock, word ,30, 0); //when I put this line code
starts messing up.
puts(word);
if(pid==0)
{
close(1);
dup(fd[1]);
close(fd[0]);
close(fd[1]);
char *cat_args[] = {"/bin/cat", "GameData.txt", NULL};
if(execv(cat_args[0], cat_args)<0)
{
printf("Error in execv! %s\n", strerror(errno));
}
exit(0);
}
if(pid > 0)
{
close(0);
dup(fd[0]);
close (fd[1]);
close(fd[0]);
puts("test2");
FILE *fp2;
if ((fp2 = popen("grep -w tries", "r")) == NULL)
{
perror("popen failed");
return NULL;
}
puts("test3");
size_t str_size = 1024;
char *stringts2 = malloc(str_size);
if (!stringts2)
{
perror("stringts allocation failed");
return NULL;
}
puts("test4");
stringts2[0] = '\0';
char buf[128];
size_t n;
puts("test5"); //when I use the recv() program gets stuck here.
while ((n = fread(buf, 1, sizeof(buf) - 1, fp2)) > 0)
{
puts("test10");
buf[n] = '\0';
size_t capacity = str_size - strlen(stringts2) - 1;
while (n > capacity)
{
str_size *= 2;
stringts2 = realloc(stringts2, str_size);
if (!stringts2)
{
perror("stringts realloation failed");
return NULL;
}
capacity = str_size - strlen(stringts2) - 1;
}
strcat(stringts2, buf);
}
puts("test6");
if (pclose(fp2) != 0)
{
perror("pclose failed");
return NULL;
}
puts("test7");
if(send(new_sock, stringts2, 10000, 0)<0)
{
printf("Error in send! %s\n", strerror(errno));
}
}
return NULL;
}
Few notes:
I am aware that in this particular piece of code I am not using the word sent by the client, hence why some lines are as comments, I will implement this when my problem gets fixed.
I am using popen() as I want to return the output of catgrep().
I isolated the problem and not it's only happening when I include the recv() function.
The word I am sending is being printed when I use recv() so the function isn't causing errors but it's messing up other parts.
UPDATE:
As suggested by someone in the comments I changed the way I receive the word sent by my client, I am now using the following:
int count = 0;
int total = 0;
while ((count = recv(new_sock, &word[total], sizeof word - count, 0)) > 0)
{
total=total+count;
}
if (count==-1)
{
perror("error in recv()");
}
Still having the same problem and same output.
The basic problem is that you are confusing strings and byte streams -- they're not the same thing.
In your client, you send some data with:
char word[30];
fgets(word, 30, stdin);
if(send(sock, &word , 30, 0)<0)
This will read a line (including a newline) into the beginning of an on-stack buffer, and then send the entire buffer, including whatever garbage happens to be in it after the end of the string. You probably don't want the newline, maybe don't want the NUL terminator, and certainly don't want the garbage.
In addition, you don't check the return value of send for a short send -- in some (admittedly rare) situations, a send might not send all the data you request.
On the reading side you don't check the return value of recv to see how many bytes you got, which may be different from what you expect -- there's no guarentee that there will be 1:1 correspondence between send and recv calls on a connection. One send might get broken up and split across multiple recvs, and several sends might have their data combined and returned in one recv. So you always need to check the return value of recv to see how many bytes you actually got.

I am unable to print message recived from client side in c server using socket?

In debugging I can see that values of rx_buffer changes to what is send from client but printf function and even fputs function is not printng the value on terminal or updating the output file
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <unistd.h>
// Constants defined
#define SERVER_PORT 3333
#define RX_BUFFER_SIZE 1024
#define TX_BUFFER_SIZE 1024
#define MAXCHAR 1000 // max characters to read from txt file
// Global variables
struct sockaddr_in dest_addr;
struct sockaddr_in source_addr;
char rx_buffer[RX_BUFFER_SIZE]; // buffer to store data from client
char tx_buffer[RX_BUFFER_SIZE]; // buffer to store data to be sent to client
char ipv4_addr_str[128]; // buffer to store IPv4 addresses as string
char ipv4_addr_str_client[128]; // buffer to store IPv4 addresses as string
int listen_sock;
char line_data[MAXCHAR];
FILE *input_fp, *output_fp;
int socket_create(struct sockaddr_in dest_addr, struct sockaddr_in source_addr){
int addr_family;
int ip_protocol;
dest_addr.sin_addr.s_addr = htonl(INADDR_ANY);
dest_addr.sin_family = AF_INET;
dest_addr.sin_port = htons(SERVER_PORT);
addr_family = AF_INET;
ip_protocol = IPPROTO_IP;
int sock,p;
printf("Create the socket\n");
sock=socket(addr_family , SOCK_STREAM , 0);
if((bind(sock, (struct sockaddr *)&dest_addr, sizeof(dest_addr)))<0){
perror("Bind failed.");
}
else{
printf("bind done");
}
char client[100];
listen(sock,1);
printf("Waiting for incoming connections...\n");
p = accept(sock, (struct sockaddr *)&source_addr, (socklen_t*)&source_addr);
if(p<0){ perror("accept failed");} printf("Client Address=%s\n",inet_ntop(AF_INET,&source_addr.sin_addr,client,sizeof(client)));
return p;
}
int receive_from_send_to_client(int sock){
char mess[10]="hello";
int len;
len=recv(sock , rx_buffer, sizeof(rx_buffer),0);
send(sock , mess , 5,0);
return 0;
}
int main() {
char *output_file_name = "data_from_client.txt";
// Create socket and accept connection from client
int sock = socket_create(dest_addr, source_addr);
output_fp = fopen(output_file_name, "w");
if (output_fp == NULL){
printf("Could not open file %s\n",output_file_name);
return 1;
}
while (1) {
receive_from_send_to_client(sock);
printf("%s",rx_buffer);
fputs(rx_buffer, output_fp);
fputs("\n", output_fp);
}
return 0;
}
In debugging I can see that values of rx_buffer are changing but not able to put that in file or print the message.
Note:- I am sending message from a python client.
in while ,you should open your file always and after putting data into the file close file descriptor properly.
see this code in main(),
int main() {
char *output_file_name = "data_from_client.txt";
// Create socket and accept connection from client
int sock = socket_create(dest_addr, source_addr);
while (1) {
output_fp = fopen(output_file_name, "a+");
if (output_fp == NULL){
printf("Could not open file %s\n",output_file_name);
return 1;
}
receive_from_send_to_client(sock);
printf("%s",rx_buffer);
fprintf(output_fp,"%s",rx_buffer);
fclose(output_fp);
}
return 0;
}

Send file size and then the file itself

client-side code:
#include <stdio.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <string.h>
#include <netdb.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
void error(char * msg){
perror(msg);
exit(0);
}
// Returns an string array from function
char *buff(const char *path){
int end = 0;
unsigned char * buf;
int f_write = open(path,O_RDONLY);
end = lseek(f_write,0,SEEK_END);
lseek(f_write,0,SEEK_SET);
buf =(char*)malloc(sizeof(char*)*(end+1));
read(f_write,buf,end);
close(f_write);
buf[end+1]= '\0';
return buf;
}
//connects to the socket
int connection(int portno,struct hostent * server,int sockfd){
struct sockaddr_in serv_addr;
int conn =0;
bzero((char *)&serv_addr,sizeof(serv_addr));
serv_addr.sin_family= AF_INET;
bcopy((char*)server->h_addr,(char *)&serv_addr.sin_addr.s_addr,server->h_length);
serv_addr.sin_port = htons(portno);
conn = connect(sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr));
return conn;
}
int main(int argc, char *argv[]) {
int sockfd = -1;
int check =0;
char projname[100]= "project1";
int portno = -1;
int conn = -1;
int file_size =0;
ssize_t len;
int n = -1;
struct hostent *server;
char buffer[256];
int fd =0;
if(argc < 3){
fprintf(stderr,"usage %s hostname port\n",argv[0]);
exit(0);
}
// getting the portnumber
portno = atoi(argv[2]);
sockfd = socket(AF_INET,SOCK_STREAM,0);
if(sockfd < 0){
error("Error opening socket");
}
// getting the hostname
server = gethostbyname(argv[1]);
if(server == NULL){
fprintf(stderr,"Error no such host\n");
exit(0);
}
conn = connection(portno,server,sockfd);
if(conn < 0){
printf("%s\n",strerror(errno));
}
int path = open("text.txt",O_CREAT | O_WRONLY, 0644);
if(path < 0){
printf("%s\n",strerror(errno));
}
int remain_data = file_size;
printf("Printing out the file size ");
printf("%d\n",file_size);
char *buffer1 = (char*)malloc(sizeof(char)*file_size+1);
len = recv(sockfd,buffer1,BUFSIZ,0);
printf("%d",len);
buffer1[file_size]= '\0';
printf("printing the sentence\n");
printf("%s\n",buffer1);
int total_read_bytes =0;
int nread =0;
return 0;
}
server-side code
#include <unistd.h>
#include <stdio.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <string.h>
#include <dirent.h>
#include <fcntl.h>
#include <sys/sendfile.h>
#include <sys/stat.h>
#include <sys/socket.h>
void error(char * msg){
perror(msg);
exit(1);
}
int main(int argc, char const *argv[]){
int sockfd =-1;
int newsockfd = -1;
int portno = -1;
int clilen = -1;
int remain_data =0;
char buffer[300];
char buffer1[300];
int peer_socket = -1;
struct sockaddr_in serv_addr,cli_addr;
int n = -1;
struct stat file_stat;
char file_size[256];
ssize_t len;
int sent_bytes =0;
int path = open("project1/text.txt",O_RDONLY);
read(path,buffer1,30);
buffer1[31]= '\0';
printf("%s\n",buffer1);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd <0){
error("Error opening socket");
}
bzero((char*) &serv_addr,sizeof(serv_addr));
portno=atoi(argv[1]);
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
if(bind(sockfd,(struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0){
error("Error on Binding");
}
listen(sockfd,5);
int fd = open("project1/text.txt",O_RDONLY);
fstat(fd,&file_stat);
clilen = sizeof(cli_addr);
peer_socket = accept(sockfd,(struct sockaddr *)&cli_addr, &clilen);
sprintf(file_size,"%d",file_stat.st_size);
//sends file size
len = send(peer_socket,file_size,sizeof(file_size),0);
if(peer_socket <0){
error("Error on accept");
}
off_t offset = 0;
remain_data = file_stat.st_size;
//send the file
while(((sent_bytes=sendfile(peer_socket,fd,&offset,remain_data))>0) &&( remain_data>0)){
fprintf(stdout,"1.Server sent %d bytes from files data, offset is now : %d and remaining data = %d\n",sent_bytes, offset,remain_data);
remain_data -=sent_bytes;
fprintf(stdout, "2. Server sent %d bytes from files data, offest is not: %d and remaing data = %d\n",sent_bytes, offset,remain_data);
}
return 0;
}
I am able to get the size of my file from server side but I am unable to get file content from my server on client side. My client prints out an empty space where the data of the file is supposed to be, I don't know if I am using the recv function correctly the file correctly.
P.S I understand that I must close the sockets when finished.
For safety and robustness, you must check the return values of all the standard library functions you call to check for errors. For recv() and read(), however, you must check and appropriately handle return values for correctness. These functions do not guarantee to transfer the full number of bytes requested, and for network connections it is reasonably common that they don't. If you want to fully transfer a specific number of bytes then you must be prepared to use multiple recv() or read() calls to do so, generally by calling the function in a loop.
You do not check the return value of your recv() call, so if you have a short read -- or if there is an error or if the remote side closes the connection without sending anything -- then your client will not notice, and will simply output whatever garbage happens to be in the buffer.

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