C Socket Server is unable to terminate connection? - c

I have made a Socket server and client.the client selects the pdf file and sends it to the server.This code runs perfectly on local machine i.e Server and client run on same host,the file is transfered on the server side and opens up with the content but when i run server and client on different hosts i encounter the following problem the Server is unable to quit and file transfered is getting overwritten at the server side,thus unable to show file content,like if i am sending a 240 kb file from client the file received at the server is of 2 GB.
I am programming in qt creator,and the client is a Gui application that also runs Socket client code while server is a console project.
This is server.cpp
#include <QtCore/QCoreApplication>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define Size 2048
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
int s, fd, len;
struct sockaddr_in my_addr;
struct sockaddr_in remote_addr;
socklen_t sin_size;
char buf[BUFSIZ];
FILE *fp = fopen("/home/D.A.D19/Desktop/Filecopy/Q7Basic_essentials.pdf","a+");
memset(&my_addr, 0, sizeof(my_addr));
my_addr.sin_family = AF_INET;
my_addr.sin_addr.s_addr = inet_addr("192.168.103.128");
my_addr.sin_port = htons(8000);
if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
qWarning("socket");
return 1;
}
if (bind(s,(struct sockaddr *)&my_addr,sizeof(struct sockaddr))<0)
{
qWarning("bind");
return 1;
}
listen(s, 5);
sin_size = sizeof(struct sockaddr_in);
if ((fd =accept(s,(struct sockaddr *)&remote_addr,&sin_size)) < 0)
{
qWarning("accepted client %s\n", inet_ntoa(remote_addr.sin_addr));
return 1;
}
len = send(fd, "Welcome to my server\n", 21, 0);
while(1)
{
len = recv(fd,buf,Size,0);
The problem is here
if (strcmp(buf,"quit") == 0){
qWarning("Connection terminated");
break;
}
fwrite(buf,Size,1, fp);
memset(buf,0,Size);
}
fclose(fp);
close(fd);
close(s);
return a.exec();
}
This is Client.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QLabel>
#include <QPushButton>
#include <QFileDialog>
#include <QLineEdit>
#include <QString>
#include <QtCore/QCoreApplication>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define SIZE 2048
QString Path;
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
QLabel *label1 = new QLabel(this);
label1->setText("FileName");
label1->setGeometry(15,25,70,30);
label1->show();
QPushButton *pushbutton = new QPushButton(this);
pushbutton->setText("Browse");
pushbutton->setGeometry(180,28,90,25);
pushbutton->show();
QObject::connect(pushbutton,SIGNAL(clicked()),this, SLOT(browse()));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::browse()
{
int s, len;
struct sockaddr_in remote_addr;
char buf[BUFSIZ];
memset(&remote_addr, 0, sizeof(remote_addr));
remote_addr.sin_family = AF_INET;
remote_addr.sin_addr.s_addr = inet_addr("192.168.103.128");
remote_addr.sin_port = htons(8000);
QLineEdit *line = new QLineEdit(this);
line->setGeometry(82,28,90,25);
QString filename = QFileDialog::getOpenFileName(this,tr("Find files"),
"/home/D.A.D19/Desktop");
line->setText(filename);
line->show();
if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
qWarning("socket");
//return 1;
}
if (::connect(s, (struct sockaddr *)&remote_addr, sizeof(struct sockaddr)) < 0)
{
qWarning("connect");
//return 1;
}
qWarning("connected to server \n");
len = recv(s, buf, BUFSIZ, 0);
qWarning("%s \n",buf);
buf[len] = '\0';
sprintf(buf, "%s", qPrintable(filename));
FILE *fp = fopen(buf,"r");
while(1)
{
if(feof(fp))
{
strcpy(buf,"quit");
send(s,buf,SIZE,0);
break;
}
if(!feof(fp))
{
int count = fread(buf,SIZE,1,fp);
len = send(s, buf,SIZE, 0);
memset(buf,0,SIZE);
}
}
fclose(fp);
::close(s);
return;
}

When you enter the string quit, it will also have the \n.
So when you compare the string, compare like this:
if (strcmp(buf,"quit\n") == 0)
And then execute the code. Now the string will be matched and connection will be terminated.

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.

recvfrom is not receiving any data, but client is sending the message successfully

I have client-server program where I created the socket with sctp protocol and client and server has a onetomany relation.
when I run the client code the return value of sendto function is greater than zero. But I don't see any message in the server code output.
Even when the server code is not running and only the client code is running, the client code shows successful message sent. How can it be when the server sockeet is not even open?
/*
* Compile:
*
* gcc sctp.c -o server -lsctp
*
* Invoke:
*
* ./client
* ./server
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <libgen.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netinet/sctp.h>
#include <arpa/inet.h>
#define MY_PORT_NUM 21233
static void die(const char *s) {
perror(s);
exit(1);
}
static void server(void) {
int listen_fd, conn_fd, flags, ret, in;
struct sctp_sndrcvinfo sndrcvinfo;
struct sockaddr_in servaddr = {
.sin_family = AF_INET,
.sin_addr.s_addr = htonl(INADDR_ANY),
.sin_port = htons(MY_PORT_NUM),
};
struct sockaddr_in client_addr;
socklen_t clilen=sizeof(client_addr);
struct sctp_initmsg initmsg = {
.sinit_num_ostreams = 5,
.sinit_max_instreams = 5,
.sinit_max_attempts = 4,
};
listen_fd = socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP);
if (listen_fd < 0)
die("socket");
ret = bind(listen_fd, (struct sockaddr *) &servaddr, sizeof(servaddr));
if (ret < 0)
die("bind");
ret = listen(listen_fd, initmsg.sinit_max_instreams);
if (ret < 0)
die("listen");
for (;;) {
char buffer[1024];
printf("Waiting for connection\n");
in = recvfrom(listen_fd, buffer, sizeof(buffer),0,(struct sockaddr*)&client_addr,&clilen);
printf("%d\n",in);
if (in > 0) {
printf("Received data: %s\n", buffer);
fflush(stdout);
}
sleep(2);
}
close(listen_fd);
}
static void client(void) {
int conn_fd, ret;
const char *msg = "Hello, Server!";
struct sockaddr_in servaddr = {
.sin_family = AF_INET,
.sin_port = htons(MY_PORT_NUM),
.sin_addr.s_addr = inet_addr("127.0.0.1"),
};
conn_fd = socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP);
if (conn_fd < 0)
die("socket()");
int i;
for(i=0;i<4;i++){
printf("before sending\n");
ret = sendto(conn_fd, (void *) msg, strlen(msg) + 1,0,(struct sockaddr*)&servaddr,sizeof(struct sockaddr));
printf("after sending\n");
if (ret < 0)
printf("failed to send %d\n",i);
else
printf("success %d\n",i);
sleep(2);
}
close(conn_fd);
}
int main(int argc, char **argv) {
if (strstr(basename(argv[0]), "server"))
server();
else
client();
return 0;
}
this code works when I run the client and server in same machine with loopback IP 127.0.0.1 but when I run them on two different remote machines I am facing this issue.

TCP write() prints char* to itself rather than to buffer only on first socket connection, but works OK on second connection onwards

On the first connection to the Server socket by a Client, the Server prints the output to itself, and leaves the Client blocked. But the second Client onwards receives the output from the Server.
The buffer that is expected to output to the Client is the server uptime.
Why does this happen, is there a way to immediately send the output to the Client and not block it?
To replicate, run 'ruptimeServer' on one terminal, and run 'ruptimeClient [localIPAddress] [serverIPAddress]'.
Below is an example of the I/O to the Server.
[user#linux-3 Lab2]$ ./ruptimeServer
Awaiting connection.
20:42:05 up 2 days, 17:38, 5 users, load average: 0.00, 0.01, 0.06 <-- buffer
Write Success
Awaiting connection.
Write Success
Awaiting connection.
Write Success
Awaiting connection.
^CCaught Ctrl+C, closing all connections.
Below is the I/O to the Client.
[user#linux-3 Lab2]$ ./ruptimeClient 127.0.0.1 10.24.87.66
Connection Success.
^C
[user#linux-3 Lab2]$ ./ruptimeClient 127.0.0.1 10.24.87.66
Connection Success.
10.24.87.66: 20:42:14 up 2 days, 17:38, 5 users, load average: 0.00, 0.01, 0.06
[user#linux-3 Lab2]$ ./ruptimeClient 127.0.0.1 10.24.87.66
Connection Success.
10.24.87.66: 20:42:18 up 2 days, 17:38, 5 users, load average: 0.00, 0.01, 0.06
Below is the code for Server.
#include <stdio.h>
#include <stdlib.h>
#include <sys/sysinfo.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <signal.h>
#include <sys/select.h>
char* get_uptime();
void sig_handl(int sig_num);
int sersock, consock;
int main(int argc, char* argv[]){
struct sockaddr_in serveraddr, clientaddr;
struct sigaction sigIntHandler;
int on = 1;
sigIntHandler.sa_handler = sig_handl;
sigemptyset(&sigIntHandler.sa_mask);
sigIntHandler.sa_flags = 0;
char input_buffer[1024] = {0};
int len = sizeof(clientaddr);
char* IP_ADDRESS = "192.168.254.11";
if((sersock = socket(PF_INET, SOCK_STREAM, 0)) < 0){
perror("socket() error");
exit(1);
}
serveraddr.sin_family = PF_INET;
serveraddr.sin_port = htons(28189);
serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
if(bind(sersock, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) < 0){
perror("bind() error");
exit(1);
}
if(listen(sersock, 10) < 0){
perror("listen() error");
exit(1);
}
char *output;
output = malloc(sizeof(char) * 1024);
signal(SIGINT, sig_handl);
while(1){
printf("Awaiting connection.\n");
if(consock = accept(sersock, (struct sockaddr *)&clientaddr, &len) < 0){
perror("accept() error");
exit(1);
}
output = get_uptime();
if(write(consock, output, 1024) < 0){
perror("write() error");
exit(1);
}
printf("Write Success\n");
close(consock);
}
close(sersock);
}
char * get_uptime(){ //returns uptime on server
char *buffer;
buffer = malloc(sizeof(char) * 1024);
FILE* file = popen("uptime", "r");
fgets(buffer, 100, file);
pclose(file);
return buffer;
}
void sig_handl(int sig_num){
printf("Caught Ctrl+C, closing all connections.\n");
close(consock);
close(sersock);
exit(0);
}
Below is the code for Client.
#include <stdio.h>
#include <stdlib.h>
#include <sys/sysinfo.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/select.h>
int main(int argc, char* argv[]){
if(argc != 3){
printf("Not enough arguments. To run, \"./ruptimeClient <localhost_IP> <server_IP>\"\n");
return 0;
}
struct sockaddr_in remoteaddr;
char input_buffer[100];
//input_buffer = malloc(sizeof(char) * 100);
int clisock;
char* SERVER_IP = argv[2];
if((clisock = socket(PF_INET, SOCK_STREAM, 0)) < 0){
perror("socket() error");
exit(1);
}
remoteaddr.sin_family = PF_INET;
remoteaddr.sin_port = htons(28189);
remoteaddr.sin_addr.s_addr = inet_addr(SERVER_IP);
if(connect(clisock, (struct sockaddr *)&remoteaddr, sizeof(remoteaddr)) < 0){
perror("Connection failed");
exit(1);
}
printf("Connection Success.\n");
if(read(clisock, input_buffer, 100) < 0){
perror("read() error");
exit(1);
}
//input_buffer = "test";
printf("%s: %s", SERVER_IP, input_buffer);
close(clisock);
return 0;
}
The problem is here:
if(consock = accept(sersock, (struct sockaddr *)&clientaddr, &len) < 0){
That's parsed as if you wrote this:
if(consock = (accept(sersock, (struct sockaddr *)&clientaddr, &len) < 0)){
As a result, consock ends up getting set to 0, which when interpreted as a file descriptor, means standard input. This then gets closed after the first client (the one that hangs), so it's available for subsequent clients, which then get reassigned that now-free FD number. To fix it, add explicit parentheses, like this:
if((consock = accept(sersock, (struct sockaddr *)&clientaddr, &len)) < 0){
the following proposed code:
is for the server
cleanly compiles
does not leak memory
incorporates the comments to the OPs question
and now, the proposed code for the server:
#include <stdio.h>
#include <stdlib.h>
#include <sys/sysinfo.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <signal.h>
#include <sys/select.h>
#include <unistd.h>
#include <string.h>
char* get_uptime( char *buffer, int size );
void sig_handl(int sig_num);
int sersock, consock;
int main( void )
{
struct sockaddr_in serveraddr, clientaddr;
struct sigaction sigIntHandler;
//int on = 1;
sigIntHandler.sa_handler = sig_handl;
sigemptyset(&sigIntHandler.sa_mask);
sigIntHandler.sa_flags = 0;
//char input_buffer[1024] = {0};
socklen_t len = sizeof(clientaddr);
//char* IP_ADDRESS = "192.168.254.11";
if((sersock = socket(PF_INET, SOCK_STREAM, 0)) < 0)
{
perror("socket() error");
exit(1);
}
serveraddr.sin_family = PF_INET;
serveraddr.sin_port = htons(28189);
serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
if(bind(sersock, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) < 0)
{
perror("bind() error");
exit(1);
}
if(listen(sersock, 10) < 0)
{
perror("listen() error");
exit(1);
}
char *output;
int size = 1024;
char buffer[ size ];
signal(SIGINT, sig_handl);
while(1)
{
printf("Awaiting connection.\n");
if( (consock = accept(sersock, (struct sockaddr *)&clientaddr, &len)) < 0)
{
perror("accept() error");
exit(1);
}
output = get_uptime( buffer, size );
if( write( consock, output, strlen( output ) ) < 0 )
{
perror("write() error");
exit(1);
}
printf("Write Success\n");
close(consock);
}
close(sersock);
}
char * get_uptime( char *buffer, int size )
{ //returns uptime on server
FILE* file = popen("uptime", "r");
fgets( buffer, size, file );
pclose(file);
return buffer;
}
void sig_handl(int sig_num)
{
(void)sig_num;
printf("Caught Ctrl+C, closing all connections.\n");
close(consock);
close(sersock);
exit(0);
}

modify c socket program to send file from server to client

Modify the following socket program and let the server send a file to the client.
I'm stuck with this i can't figure this out.
below is the server and client that where given to me. right now the server will send the client the time stamp.
Socket Server Example (server.c)
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <time.h>
int main(int argc, char *argv[])
{
int listenfd = 0, connfd = 0;
struct sockaddr_in serv_addr;
char sendBuff[1025];
time_t ticks;
listenfd = socket(AF_INET, SOCK_STREAM, 0);
memset(&serv_addr, '0', sizeof(serv_addr));
memset(sendBuff, '0', sizeof(sendBuff));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(5000);
bind(listenfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
listen(listenfd, 10);
while(1)
{
connfd = accept(listenfd, (struct sockaddr*)NULL, NULL);
ticks = time(NULL);
snprintf(sendBuff, sizeof(sendBuff), "%.24s\r\n",
ctime(&ticks));
write(connfd, sendBuff, strlen(sendBuff));
close(connfd);
sleep(1);
}
}
Socket Client Example (client.c)
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <arpa/inet.h>
int main(int argc, char *argv[])
{
int sockfd = 0, n = 0;
char recvBuff[1024];
struct sockaddr_in serv_addr;
if(argc != 2)
{
printf("\n Usage: %s <ip of server> \n",argv[0]);
return 1;
}
memset(recvBuff, '0',sizeof(recvBuff));
if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
printf("\n Error : Could not create socket \n");
return 1;
}
memset(&serv_addr, '0', sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(5000);
if(inet_pton(AF_INET, argv[1], &serv_addr.sin_addr)<=0)
{
printf("\n inet_pton error occured\n");
return 1;
}
if( connect(sockfd, (struct sockaddr *)&serv_addr,
sizeof(serv_addr)) < 0)
{
printf("\n Error : Connect Failed \n");
return 1;
}
while ( (n = read(sockfd, recvBuff, sizeof(recvBuff)-1)) > 0)
{
recvBuff[n] = 0;
if(fputs(recvBuff, stdout) == EOF)
{
printf("\n Error : Fputs error\n");
}
}
if(n < 0)
{
printf("\n Read error \n");
}
return 0;
}
If you don't want to or can't read the whole content of the file you wish to send at once into memory, use a loop with your buffer:
#include <fcntl.h>
if (argv[1]) // or whereever you get the file name from
{
int fd = open(argv[1], O_RDONLY);
if (fd < 0) perror(argv[1]);
else
{
ssize_t n;
while (n = read(fd, sendBuff, sizeof sendBuff), n > 0)
if (send(connfd, sendBuff, n, MSG_NOSIGNAL) < 0)
{ perror("send"); break; }
close(fd);
if (n < 0) perror("read");
}
}
In the client use a similar loop. Be aware that the file might contain NUL characters, so functions like fputs, operating on C strings, are inept.
while ((n = read(sockfd, recvBuff, sizeof recvBuff)) > 0)
if (write(1, recvBuff, n) < 0) perror("write");
Read the content of the file you wish to send, and save it into a string:
char *loadFileContent(char *fileName, size_t *len){
FILE* input_file = fopen(fileName, "rb");
size_t stat;
if(!input_file){
OCSP_ERR_INDEX = OCSP_LOG_ERR_load_file_fail;
return NULL;
}
fseek(input_file, 0, SEEK_END);
long int input_file_size = ftell(input_file);
rewind(input_file);
char *file_contents = malloc((input_file_size + 1) * (sizeof(char)));
stat = fread(file_contents, sizeof(char), (size_t) input_file_size, input_file);
if(stat<1){
OCSP_ERR_INDEX = OCSP_LOG_ERR_load_file_fail;
return NULL;
}
fclose(input_file);
file_contents[input_file_size] = 0;
*len = (size_t) input_file_size;
return file_contents;
}
In your code, modify the line in server that is supposed to send response to client.
So this line write(connfd, sendBuff, strlen(sendBuff)); becomes:
size_t len;
char *text = loadFileContent("myfile.txt", &len);
write(connfd, text, len);

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