I have client.c and server.c , I'm trying to send a file from client to server and from server to client...
The file is received by the server but when the server sends the file , the client stops or does not receive the file ,
The sendFile() function:
void sendfile(int fd,char* filename)
{
char buff[0x1000];
FILE *file = fopen(filename, "rb");
if (!file)
{
printf("Can't open file for reading");
return;
}
while (!feof(file))
{
int rval = fread(buff, 1, sizeof(buff), file);
if (rval < 1)
{
printf("Can't read from file\n");
fclose(file);
return;
}
int off = 0;
do
{
int sent = send(fd, &buff[off], rval - off, 0);
printf("Sending ...\n");
if (sent < 1)
{
printf("Can't write to socket");
fclose(file);
return;
}
printf("[SendFile]Fisierul a fost trimis!\n");
off += sent;
}
while (off < rval);
}
fclose(file);
}
The getFile():
void getFile(int fd,char* filename)
{
int rval;
char buff[0x1000];
FILE *file = fopen(filename, "w+");
if (!file)
{
printf("Can't open file for writing");
return;
}
do
{
rval = recv(fd, buff, sizeof(buff), 0);
if (rval < 0)
{
printf("Can't read from socket");
fclose(file);
return;
}
if (rval == 0)
break;
int off = 0;
do
{
int written = fwrite(&buff[off], 1, rval - off, file);
printf("[server]Writing %d bytes\n",written);
if (written < 1)
{
printf("Can't write to file");
fclose(file);
return;
}
off += written;
}
while (off < rval);
printf("[server]File received!\n");
}
while(1);
fclose(file);
}
The client main():
int main (int argc, char *argv[])
{
int sd;
struct sockaddr_in server;
if (argc != 2)
{
printf ("[client] Sintaxa: %s <filename>\n", argv[0]);
return -1;
}
if ((sd = socket (AF_INET, SOCK_STREAM, 0)) == -1)
{
perror ("[client] Eroare la socket().\n");
return errno;
}
server.sin_family = AF_INET;
server.sin_addr.s_addr = inet_addr("127.0.0.1");
server.sin_port = htons (port);
if (connect (sd, (struct sockaddr *) &server,sizeof (struct sockaddr)) == -1)
{
perror ("[client]Eroare la connect().\n");
return errno;
}
sendfile(sd,"test.cpp");
printf("File sent\n");
getFile(sd,"server.c");
close (sd);
}
The loop from server.c
while (1)
{
int client;
int length = sizeof (from);
printf ("[server]Asteptam la portul %d...\n",port);
fflush (stdout);
client = accept (sd, (struct sockaddr *) &from, &length);
if (client < 0)
{
perror ("[server]Eroare la accept().\n");
continue;
}
if((pid=fork()) == 0 )
{
getFile(client,"test.cpp");
sendfile(client,"server.c");
printf("File sent\n");
close(client);
}
}
To Start with.
accept(), connect(), recv() .. all are blocking calls so in theory your program can get blocked anywhere in these calls until you use non blocking sockets. From the program it looks like you are using blocking sockets
I would suggest you to read a good socket programming tutorial like this one first https://beej.us/guide/bgnet/
Secondly
I would suggest you to have a tool like wireshark or any other packet analyzer tool running to debug your problem.
Lastly you can do something like the following code snippets to try
Set sockets to non blocking mode using fnctl API call.
int rc = fcntl(newFd, F_GETFL,0);
rc |= O_NONBLOCK;
rc = fcntl(newFd, F_SETFL,rc);
Poll the socket for events You can use something like select,poll for the
same. Here is a nice example for select in the Beej's tutorial.
https://beej.us/guide/bgnet/html/multi/selectman.html
Handle errors correctly. Non blocking sockets can return a EAGAIN or EWOULDBLOCK error which has to be handled correctly. The error means the socket is not readable or writable at the moment look for events and try again. Someting on the lines of.
rval = recv(fd, buff, sizeof(buff), 0);
if (rval < 0)
{
if((errno == EWOULDBLOCK)||(errno ==EAGAIN))
{
continue;
}
else
//cleanup
}
tre problem was the do { ... } while(1); from getFile ...so I deleted the loop...
Related
I am a C beginner. I want to send a file by TCP. The client reads content from a txt file and sent it to server. Read method is ok. It reads the specified bytes from the file. Send method dose not throw any exception. However the server receives nothing. I try to solve it for a whole day. I fail.
Please help me check what is wrong with my code.
As comment advice, I edit my code again. Now there are two problem. One is that in the client loop the return values from client fread() and send() is greater than 0 for the first two times while the server accept() is still blcoked without getting message from client.
The second problem. In the third client loop, the return value of client fread() is still greater than 0, but the return value of send() is -1.I try to open the file in binary mode rb instead of r. It is the same problem.
the edited client code:
#include <stdio.h>
#include <winsock.h>
#include <time.h>
#pragma comment(lib, "WS2_32.lib")
#define MAXLINE 1024*4
SOCKET sockClient;// = socket(AF_INET,SOCK_DGRAM,0);
SOCKADDR_IN servAddr;
int main(void) {
WSADATA wsd;
FILE *fp;
int read_len;
char buf2[MAXLINE];
time_t t_start, t_end;
if ((fp = fopen("file.txt", "r")) == NULL) {
perror("Open file failed\n");
exit(0);
}
if (WSAStartup(MAKEWORD(2, 2), &wsd) != 0) {
printf("WSAStartup failed !\n");
return 1;
}
sockClient = socket(AF_INET, SOCK_STREAM, 0);
servAddr.sin_family = AF_INET;
servAddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
servAddr.sin_port = htons(5000);
/* connect the server commanted by guoqingbo*/
int i_ret = connect(sockClient, (struct sockaddr *) &servAddr, sizeof(struct sockaddr));
if (-1 == i_ret) {
perror("Connect socket failed!\n");
exit(0);
}
printf("client starts\n");
t_start = time(NULL);
while (1) {
read_len = fread(buf2, sizeof(char), MAXLINE, fp);
if (read_len < 0) {
perror("read data failed\n");
break;
} else if (read_len == 0) {
printf("read finished\n");
}
int send_len = send(sockClient, buf2, read_len, 0);
if (send_len < 0) {
perror("Send data failed\n");
exit(0);
} else if (send_len == 0) {
printf("send finished\n");
break;
}
}
t_end = time(NULL);
printf("The time used %f s\n", difftime(t_end, t_start));
fclose(fp);
closesocket(sockClient);
WSACleanup();
return 0;
}
the edited server code:
#include <stdio.h>
#include <WINSOCK2.H>
#include <strings.h>
#include <stdlib.h>
#pragma comment(lib, "WS2_32.lib")
#define BUF_SIZE 1024*4
SOCKET socketSrv;
SOCKADDR_IN addrSrv;
SOCKADDR_IN addrClient;
char buf[BUF_SIZE];
int main(void) {
WSADATA wsd;
int nRet;
int recv_len;
FILE *fp;
if ((fp = fopen("file.txt", "w")) == NULL) {
perror("Creat file failed");
exit(0);
}
if (WSAStartup(MAKEWORD(2, 2), &wsd) != 0) {
printf("WSAStartup failed !\n");
return 1;
}
socketSrv = socket(AF_INET, SOCK_STREAM, 0);
int len = sizeof(SOCKADDR);
ZeroMemory(buf, BUF_SIZE);
addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
addrSrv.sin_family = AF_INET;
addrSrv.sin_port = htons(5000);
nRet = bind(socketSrv, (SOCKADDR *) &addrSrv, sizeof(SOCKADDR));
if (SOCKET_ERROR == nRet) {
printf("bind failed !\n");
closesocket(socketSrv);
WSACleanup();
return -1;
}
if (SOCKET_ERROR == listen(socketSrv, 10)) {
printf("Server Listen Failed: %d", WSAGetLastError());
exit(1);
}
printf("server started..\n");
while (1) {
SOCKET m_New_Socket = accept(socketSrv, (SOCKADDR *) &addrClient, &len);
if (SOCKET_ERROR == m_New_Socket) {
printf("Server Accept Failed: %d", WSAGetLastError());
break;
}
if (recv_len = recv(socketSrv, buf, BUF_SIZE, 0) < 0) {
printf("Server Receive Data Failed!");
break;
}
int write_length = fwrite(buf, sizeof(char), recv_len, fp);
if (write_length < recv_len) {
printf("File write failed\n");
break;
}
}
fclose(fp);
closesocket(socketSrv);
WSACleanup();
return 0;
}
I am required to develop a stripped down version of online IDE. It will follow a client-server architecture. Client side will have three commands.
CREATE
RUN
QUIT
When the client chooses 'create' , the command would be sent to a server. The server will open windows. The first window will be a text editor in which the user will be able to write the code. The second window will act like an automatic parser which will parse the program that the users have written in the first window. The server side will read the user program at an interval of 1 second and parse the program using Lex and yacc. Any error found in the program should be reported in window 2. If there are no errors, the window will simply state "No error".
I have done till parsing part. But i could not understand, how to open a terminal from program and print error to that terminal.
I am posting my code here.
SERVER SIDE:
#include<stdio.h>
#include<stdlib.h>
#include<string.h> // This is for string related call.
#include<errno.h> // This is for error handling.
#include<limits.h> // this is for different type limit checking.
#include<ctype.h> // This is for different type checking.
#include<fcntl.h> // This is for unblocking socket.
#include<unistd.h> // this is for different type typical system call.
#include<sys/socket.h> // This header file defines miscellaneous socket related constant, types, and function.
#include<sys/types.h> // This header file defines miscellaneous types
#include<sys/sem.h> // This header file defines semaphores related types, function.
#include<sys/wait.h> // This header file defines blocking and wait related types and function.
#include<sys/ipc.h> // This header file defines mainly interprocess communication related structures.
#include<netinet/in.h> // This header file defines system parameter related to address.
#include<arpa/inet.h> // This header file defines different types macros .
#include<time.h> // This header file is included for getting times.
#include<signal.h>
#include<netdb.h>
#include<sys/shm.h> // This header file is included for shared memory .
#define PORT "5000" // This is the port server will be listening on
#define MAX 4096
#define NAZMUL
extern void parse(FILE*,FILE*);
int listener; // Server will be listening on this socket id.
/*.....................This function convert the IP address................................*/
void *convert(struct sockaddr *sa)
{
if(sa->sa_family == AF_INET)
return &(((struct sockaddr_in *)sa)->sin_addr);
return &(((struct sockaddr_in6 *)sa)->sin6_addr);
}
/*.........................................................................................*/
/*...............We are handling SIGINT SIGNAL here..........................................*/
void sigint_handler(int sig)
{
int nbytes;
char buffer[MAX];
strcpy(buffer, "quit");
#if hi
if((nbytes = send(new_fd, buffer, strlen(buffer) + 1, 0)) < 0)
{
if(nbytes == 0)
{
printf("SERVER: client is closed\n");
close(new_fd);
close(listener);
exit(EXIT_SUCCESS);
}
else
{
perror("SERVER:");
close(new_fd);
close(listener);
exit(EXIT_FAILURE);
}
}
close(listener);
close(new_fd);
#endif
exit(EXIT_SUCCESS);
}
/*............................................................................................*/
/*.......................We are handling SIGCHLD signal here..................................*/
void sigchild_handler(int sig)
{
// waitpid() might overwrite errno, so we save and restore it:
int saved_errno = errno;
while(waitpid(-1, NULL, WNOHANG) > 0);
errno = saved_errno;
}
/*..............................................................................................*/
/*...........................We are generating random number here...............................*/
int main()
{
int yes = 1; // this for setsockopt()
int status; // this is for holding return value of getaddrinfo()
int proces_id_gedit; // this will hold return value of fork()
int flags; // this for fcntl() call
char file_name[128]; // This is for saving filename.
char command[128],filenameout[128];
FILE *fp, *output_fp;
int create_flag = 0; // To check whether create command came or not
char *line = NULL;
size_t length = 0;
ssize_t nread;
struct sigaction for_sigint, for_sigchild; // these struct, we have to pass to sigaction()
char buffer[MAX]; // this will be used in send(), recv()
int nbytes; // This will hold return value of send(), recv()
int new_fd; // newly accept()ed socket descriptor.
struct sockaddr_storage client_addr; //it will hold client socket address.
char client_IP[INET6_ADDRSTRLEN]; // It will hold the ip address of client ip address.
socklen_t addr_len; // It will hold length of client ip address.
/*................GET us an successful socket and bind it...........................................*/
struct addrinfo hints, *ref, *p;
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;
if((status = getaddrinfo(NULL, PORT, &hints, &ref)) != 0)
{
fprintf(stderr, "SERVER: getaddrinfo:%s\n",gai_strerror(status) );
exit(EXIT_FAILURE);
}
for(p = ref; p != NULL; p = p->ai_next)
{
if((listener = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1)
{
continue;
}
if(setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1)
{
perror("SERVER:");
exit(EXIT_FAILURE);
}
/*....Setting the socket in non-blocking mode...*/
if ((flags = fcntl(listener, F_GETFL, 0)) < 0)
{
perror("SERVER(flags = fcntl):");
continue;
}
if (fcntl(listener, F_SETFL, flags | O_NONBLOCK) < 0)
{
perror("SERVER( fcntl):");
continue;
}
/*..............................................*/
if(bind(listener, p->ai_addr, p->ai_addrlen) == -1)
{
continue;
}
break; // we get successfull socket and bind, so we do not need to traverse anymore.
}
if(p == NULL) //checking whether we get a successful binding socket or not
{
fprintf(stderr, "we did not get successful binding socket\n");
exit(EXIT_FAILURE);
}
freeaddrinfo(ref);
/*..................we are handling here SIGINT SIGNAL....................................*/
for_sigint.sa_handler = sigint_handler;
for_sigint.sa_flags = 0;
sigemptyset(&for_sigint.sa_mask);
if(sigaction(SIGINT, &for_sigint, NULL) < 0)
{
perror("SERVER(sigint):");
exit(EXIT_FAILURE);
}
/*............................................................................................*/
/*.......................We are handling SIGCHLD signal here.................................*/
for_sigchild.sa_handler = sigchild_handler;
for_sigchild.sa_flags = SA_RESTART;
sigemptyset(&for_sigchild.sa_mask);
if(sigaction(SIGCHLD, &for_sigchild, NULL) < 0)
{
perror("SERVER(SIGCHLD):");
exit(EXIT_FAILURE);
}
/*.............................................................................................*/
listen(listener, 5); // we are listening here.
printf("SERVER:We are waiting for connection......................................\n");
for(;;)
{
addr_len = sizeof(client_addr);
if((new_fd = accept(listener, (struct sockaddr *)&client_addr, &addr_len)) < 0) // we are accepting new connection here.
{
}
else
{
/*....Setting the socket in non-blocking mode...*/
if ((flags = fcntl(new_fd, F_GETFL, 0)) < 0)
{
perror("SERVER(flags = fcntl):");
continue;
}
if (fcntl(new_fd, F_SETFL, flags | O_NONBLOCK) < 0)
{
perror("SERVER( fcntl):");
continue;
}
/*..............................................*/
inet_ntop(client_addr.ss_family, convert((struct sockaddr *)&client_addr), client_IP, sizeof client_IP);
printf("SERVER: We got connection from %s\n",client_IP );
if( fork() == 0)
{
close(listener); // child process does not need this.
for(;;)
{
memset(buffer, 0, 4096);
if((nbytes = recv(new_fd, buffer, MAX, 0)) == 0)
{
printf("SERVER: client is closed\n");
close(new_fd);
close(listener);
exit(EXIT_SUCCESS);
}
else
{
if(strcmp(buffer, "quit") == 0)
{
memset(buffer, 0, 4096);
strcpy(buffer, "quit");
if((nbytes = send(new_fd, buffer, strlen(buffer) + 1, 0)) < 0)
{
if(nbytes == 0)
{
printf("SERVER: client is closed\n");
close(new_fd);
close(listener);
exit(EXIT_SUCCESS);
}
else
{
}
}
else
{
if(create_flag == 1)
{
remove(file_name);
remove(filenameout);
create_flag = 0;
}
printf("SERVER: Connection with client %d is closed\n",new_fd );
close(new_fd);
close(listener);
exit(EXIT_SUCCESS);
}
}
else if(strcmp(buffer, "create") == 0)
{
printf("create command came\n");
memset(buffer, 0, 4096);
strcpy(buffer, "we got create command");
if((nbytes = send(new_fd, buffer, strlen(buffer) + 1, 0)) == 0)
{
printf("SERVER: client is closed\n");
close(new_fd);
close(listener);
exit(EXIT_SUCCESS);
}
sprintf(file_name, "%d.txt",getpid() );
sprintf(filenameout,"%dout.txt",getpid());
sprintf(command,"gedit %s",file_name);
signal(SIGCHLD, SIG_IGN);
if((proces_id_gedit= fork())== 0)
{close(new_fd);
system(command);
}
else
create_flag = 1;
}
else if(strcmp(buffer, "run") == 0)
{
printf("run command came\n");
memset(buffer, 0, 4096);
output_fp = fopen(filenameout, "r");
while((nread = getline(&line, &length, output_fp)) != -1)
{
strcat(buffer, line);
}
free(line);
fclose(output_fp);
//printf("%s\n",buffer );
if((nbytes = send(new_fd, buffer, strlen(buffer) + 1, 0)) == 0)
{
if(nbytes == 0)
{
printf("SERVER: client is closed\n");
close(new_fd);
close(listener);
exit(EXIT_SUCCESS);
}
else
{
}
}
char temp[128];
sprintf(temp, "kill -9 %d",proces_id_gedit);
//printf("%s\n",temp );
system(temp);
remove(filenameout);
remove(file_name);
create_flag = 0;
}
else
{
#if nazmul
memset(buffer, 0, 4096);
strcpy(buffer, "you entered invalid command");
if((nbytes = send(new_fd, buffer, strlen(buffer) + 1, 0)) < 0)
{
if(nbytes == 0)
{
printf("SERVER: client is closed\n");
close(new_fd);
close(listener);
exit(EXIT_SUCCESS);
}
else
{}
}
#endif
}
if(create_flag == 1)
{
sleep(1);
fp = fopen(file_name, "r");
output_fp=fopen(filenameout, "w");
if ( fp != NULL)
{
//printf("we are calling parse\n");
parse(fp, output_fp);
fclose(fp);
}
fclose(output_fp);
}
}
}/*..........................................END OF FOR LOOP OF EACH CLIENT HANDLING PROCESS................*/
}/*..............................................END OF FORK IF BLOCK...........................................*/
else
{
close(new_fd); // parent does not need this
continue;
}
}/*..................................................END OF ACCEPT ELSE BLOCK....................................*/
}/*......................................................END OF OF MAIN FOR LOOP.......................................*/
}/*..........................................................END OF MAIN BLOCK.........................................................*/
I am just posting server side here. This might be big code to go through. You can answer just without reading the code. I assumed that I run both client and server on my machine.
I'm creating a program that requests a file from a server and sends back the file, creating a new file and writing the contents of that file into the new file. Everything is working perfectly except server side error messages (i.e. file doesn't exist) should be printed on the client side. Can anyone give me a clue on how to accomplish this? I'm new to C, but willing to learn more. My main problem is that if I send the message directly, the client side doesn't know that it's an error and is going to finish out and create a file and write the message into that file. I was thinking I need to send back a -1, so when client calls recv, it gets back -1 as the length and prints a message.
Here's my client:
ssize_t recvx(int sockfd, void *buf, size_t len) {
int var = recv(sockfd, buf, len, 0);
if(var != -1)
{
return var;
} else {
printf("%s \n","Did not receive.");
exit(1);
}
}
int main(int argc, char *argv[])
{
char buf[MAX_LINE];
struct addrinfo hints;
struct addrinfo *rp, *result;
int bytes_received;
int s;
char *server;
char *port;
char *file;
int fd = -1; //file descriptor
int bytes_written;
if (argc==4)
{
server = argv[1];
port = argv[2];
file = argv[3];
}
else
{
fprintf(stderr, "invalid # of arguments\n");
exit(1);
}
/* Translate host name into peer's IP address */
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = 0;
hints.ai_protocol = 0;
if ((s = getaddrinfo(server, port, &hints, &result)) != 0 )
{
fprintf(stderr, "%s: getaddrinfo: %s\n", argv[0], gai_strerror(s));
exit(1);
}
/* Iterate through the address list and try to connect */
for (rp = result; rp != NULL; rp = rp->ai_next)
{
if ((s = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol)) == -1 )
{
continue;
}
if (connect(s, rp->ai_addr, rp->ai_addrlen) != -1)
{
break;
}
close(s);
}
if (rp == NULL)
{
perror("stream-talk-client: connect");
exit(1);
}
freeaddrinfo(result);
/*send lines of text */
send(s, file, sizeof(file), 0);
while(bytes_received != 0)
{
bytes_received = recvx(s, buf, 20);
if(bytes_received == -1)
{
fprintf(stderr, "Client Error: Error receiving file \n");
exit(1);
} else {
if(fd == -1)
{
fd = open(file, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
if(fd == -1)
{
fprintf(stderr,"Client Error: Open failed \n");
exit(1);
}
bytes_written = write(fd,buf,bytes_received);
if(bytes_written == -1)
{
fprintf(stderr,"%s \n", "Client Error: Write error");
exit(1);
}
} else {
bytes_written = write(fd,buf,bytes_received);
if(bytes_written == -1)
{
fprintf(stderr,"%s \n", "Client Error: Write error");
exit(1);
}
}
}
}
if(close(fd) != 0)
{
printf("%s \n", "Client Error: File did not close successfully");
exit(1);
}
close(s);
return 0;
}
Here's my server:
int main(int argc, char *argv[])
{
struct addrinfo hints;
struct addrinfo *rp, *result;
char filename[MAX_LINE];
int s, new_s;
int bytes_transferred;
int fd; //file descriptor
struct stat statBuffer; //to hold file info
off_t offset = 0;
/* Build address data structure */
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;
hints.ai_protocol = 0;
hints.ai_canonname = NULL;
hints.ai_addr = NULL;
hints.ai_next = NULL;
/* Get local address info */
if ((s = getaddrinfo(NULL, argv[1], &hints, &result)) != 0 )
{
fprintf(stderr, "%s: getaddrinfo: %s\n", argv[0], gai_strerror(s));
exit(1);
}
/* Iterate through the address list and try to perform passive open */
for (rp = result; rp != NULL; rp = rp->ai_next)
{
if ((s = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol)) == -1 )
{
continue;
}
if (!bind(s, rp->ai_addr, rp->ai_addrlen))
{
break;
}
close(s);
}
if (rp == NULL)
{
perror("stream-talk-server: bind");
exit(1);
}
if (listen(s, MAX_PENDING) == -1)
{
perror("stream-talk-server: listen");
close(s);
exit(1);
}
freeaddrinfo(result);
/* Wait for connection, then receive and print text */
while(1)
{
if ((new_s = accept(s, rp->ai_addr, &(rp->ai_addrlen))) < 0)
{
perror("stream-talk-server: accept");
close(s);
exit(1);
}
while(bytes_transferred == recv(new_s,filename,sizeof(filename),0))
{
if(bytes_transferred == -1)
{
fprintf(stderr, "Server Error: Error receiving filename \n");
exit(1);
}
}
printf("%s \n", filename);
fd =open(filename,O_RDONLY);
if(fd < 0)
{
fprintf(stderr,"Server Error: file doesn't exist\n");
exit(1);
}
else
{
printf("%s \n","file opened successfully");
}
/*get info from file descriptor (fd) and store it in statBuffer struct */
fstat(fd, &statBuffer);
bytes_transferred = sendfile(new_s,fd,&offset,statBuffer.st_size);
if(bytes_transferred == -1)
{
fprintf(stderr, "Server Error: File not transferred successfully");
}
else
{
printf("%s \n", "File transferred successfully");
}
if(close(fd) != 0)
{
fprintf(stderr, "Server Error: File not close successfully");
}
else{
break;
}
}
close(new_s);
return 0;
}
Essentially what you're implementing is something along the lines of what HTTP and FTP servers do. Both have specific, but rather different, protocol steps for handling errors. The HTTP case is easy to understand -- the server doesn't just send back the file: it sends back a bunch of headers, then the file. The client can inspect the headers to know whether there is any file data to follow.
In a very simple case, I suspect you could implement something similar in your code without too much work -- just have the server send a one-byte response code before the rest of the file. You could have 0 (for example) to indicate that a valid file follows, and other numbers to indicate particular error conditions. The client would just read the data as it currently does, but if the first byte isn't zero, it knows that nothing else that follows (if anything does) is valid.
Or you could arrange that if the first byte was not zero, the text that follows is not the expected file, but an error message, which should be displayed by the client.
You could extent such a scheme with as much complexity as you like, until you end up with HTTP :)
I'm having a really hard time figuring out how to exit the loop on the receiver side. I have a tcp stream socket connection and I'm sending what I read from a file and putting it in the buffer. The receiver end just keeps looping writing the same info over and over. I'm sure it's because i'm not decrementing nRecv so it never hits the if(nRecv == 0) statement but i can't figure out how to decrement it. I'm posting the while loop for both sender and receiver hopefully someone can point me in the right direction.
sender
/* prepare file to send */
pf = fopen("input.txt", "rb");
if(pf == NULL)
{
printf("The file you want to send was not found");
return(1);
}
else
{
while (!feof(pf))
{
nRead = fread(bufferin, sizeof(char), 256, pf);
if (nRead <= 0)
printf("ERROR reading file");
while (nRead > 0)
{
nSent = send(filesender_socket, bufferin, nRead, 0);
if (nSent < 0)
{
printf("ERROR sending from socket = %d\n", WSAGetLastError());
break;
}
if (nSent == 0)
printf("DISCONNECTED writing to socket");
//pBuf += nSent;
//nRead -= nSent;
}
}
} //end of if statement
// Close all open sockets
#ifdef WIN
//retcode = closesocket(jsender_socket);
retcode = closesocket(filesender_socket);
if (retcode < 0)
{
printf("*** ERROR - closesocket() failed \n");
exit(-1);
}
#endif
RECEIVER
//create a new socket for file transfer
filesocket = socket(AF_INET, SOCK_STREAM, 0);
if (filesocket < 0)
{
printf("*** ERROR - socket() failed \n");
exit(-1);
}
// >>> Step #2 <<<
// Fill-in my socket's address information
receiver_addr.sin_family = AF_INET; // Address family to use
receiver_addr.sin_port = htons(PORT_FILE); // Port number to use
receiver_addr.sin_addr.s_addr = htonl(INADDR_ANY); // Listen on any IP address
filebindcode = bind(filesocket, (struct sockaddr *)&receiver_addr,sizeof(receiver_addr));
if (filebindcode < 0)
{
printf("*** ERROR - file socket bind() failed \n");
exit(-1);
}
printf("receiver accepting connections\n");
//2 DEBUG LINES
printf("received a connection from: %s port %d\n",
inet_ntoa(sender_addr.sin_addr), ntohs(sender_addr.sin_port));
if (newsockfd = listen(filesocket, 2) < 0) {
printf("newsock in listen %d\n", newsockfd);
perror("listen failed");
exit(1);
}
//listen(filesocket, 2);
//while(1) //while loop for to accept files
//{
printf("\nwaiting for accept() to complete \n");
newsockfd = accept(filesocket, (struct sockaddr *) &sender_addr, &addr_len);
printf("newsock return %d", newsockfd);
if (newsockfd < 0)
{
printf("*** ERROR - accepting() failed \n");
exit(-1);
}
// start receiving file
fp = fopen("output.txt", "wb");
if (fp == NULL)
{
printf("File not found!\n");
return NULL;
}
else
{
printf("created file output.txt\n");
}
//receive file
while(1)
{
nRecv = recv(newsockfd, bufferin, 256, 0);
if (nRecv < 0)
{
printf("ERROR reading from socket = %d\n", WSAGetLastError());
break;
}
if (nRecv == 0)
break;
while (nRecv > 0)
{
printf("%s", bufferin); // debug
nWritten = fwrite(bufferin, sizeof(char), nRecv, fp);
if (nWritten <= 0)
printf("ERROR writing to file");
//nRecv -= nWritten;
}
}
printf("File Transfer complete\n\n"); //} //end of while
The return value of recv() is as follows:
>0 -- the number of bytes received
0 -- no data (async sockets only) or other socket was closed cleanly
<0 -- an error occurred.
In your sender code, you never close the socket, so your receiver waits for more data.
not sure why but now the two lines i had commented out because they weren't working now they work..
uncommented the following lines
pBuf += nSent;
nRead -= nSent;
and these on the reciver side
nRecv -= nWritten;
and it worked like a charm.
Thank you for the help.
I have a server and two client.I want to store data in different file coming from clients at a same time.
Presently I'm storing data in a same file coming from two client.And after one client send the data, second starts to send.
I want that two client send the data at same time.
Anyone can help me...
server.c
void *function1(void *ptr);
typedef struct{
int port_id;
int thread_id;
}conn_id;
int main(int argc, char *argv[])
{
conn_id conn_id1[2];
conn_id1[0].port_id=7350;
conn_id1[0].thread_id=1;
conn_id1[1].port_id=7351;
conn_id1[1].thread_id=2;
conn_id* conn_ptr;
pthread_t thread[2];
int index=0;
for(index=0;index<2;index++){
conn_ptr=&conn_id1[index];
pthread_create(&thread[index],NULL,&function1,(void*)conn_ptr);}
pthread_join(thread[0],NULL);
pthread_join(thread[1],NULL);
return 0;
}
void *function1( void *ptr)
{
//Declaring process variables.
int server_sockfd, client_sockfd;
int server_len ;
int rc ;
conn_id* conn_ptr;
conn_ptr = (conn_id*)ptr;
unsigned client_len;
char revbuf[LENGTH];
struct sockaddr_in server_address;
struct sockaddr_in client_address;
//Remove any old socket and create an unnamed socket for the server.
server_sockfd = socket(AF_INET, SOCK_STREAM, 0);
server_address.sin_family = AF_INET;
server_address.sin_addr.s_addr = htons(INADDR_ANY);
server_address.sin_port = htons(conn_ptr->port_id);
server_len = sizeof(server_address);
bzero(&(server_address.sin_zero), 8);
rc = bind(server_sockfd, (struct sockaddr *) &server_address, server_len);
printf("RC from bind = %d\n", rc ) ;
//Create a connection queue and wait for clients
rc = listen(server_sockfd, 5);
printf("RC from listen = %d\n", rc ) ;
client_len = sizeof(client_address);
client_sockfd = accept(server_sockfd, (struct sockaddr *) &client_address, &client_len);
printf("after accept()... client = %s\n", inet_ntoa(client_address.sin_addr)) ;
while(1)
{
/*Receive File from Client */
char* fr_name = "/home/server/Desktop/fr_client.dat";
FILE *fr = fopen(fr_name, "a");
if(fr == NULL)
printf("File %s Cannot be opened file on server.\n", fr_name);
else
{
bzero(revbuf, LENGTH);
int fr_block_sz = 0;
while((fr_block_sz = recv(client_sockfd, revbuf, LENGTH, 0)) > 0)
{
int write_sz = fwrite(revbuf, sizeof(char), fr_block_sz, fr);
if(write_sz < fr_block_sz)
{
error("File write failed on server.\n");
}
bzero(revbuf, LENGTH);
if (fr_block_sz == 0 || fr_block_sz != 512)
{
break;
}
}
if(fr_block_sz < 0)
{
if (errno == EAGAIN)
{
printf("recv() timed out.\n");
}
else
{
fprintf(stderr, "recv() failed due to errno = %d\n", errno);
exit(1);
}
}
printf("Ok received from client!\n");
fclose(fr);
}
/* Call the Script */
system("cd ; chmod +x script.sh ; ./script.sh");
/* Send File to Client */
char* fs_name = "/home/server/Desktop/output.txt";
char sdbuf[LENGTH]; // Send buffer
printf("[Server] Sending %s to the Client...", fs_name);
FILE *fs = fopen(fs_name, "r");
if(fs == NULL)
{
fprintf(stderr, "ERROR: File %s not found on server. (errno = %d)\n", fs_name, errno);
exit(1);
}
bzero(sdbuf, LENGTH);
int fs_block_sz;
while((fs_block_sz = fread(sdbuf, sizeof(char), LENGTH, fs))>0)
{
if(send(client_sockfd, sdbuf, fs_block_sz, 0) < 0)
{
fprintf(stderr, "ERROR: Failed to send file %s. (errno = %d)\n", fs_name, errno);
exit(1);
}
bzero(sdbuf, LENGTH);
}
printf("Ok sent to client!\n");
close(client_sockfd);
printf("[Server] Connection with Client closed. Server will wait now...\n");
while(waitpid(-1, NULL, WNOHANG) > 0);break;
}
}
If you want to receive data simultaneously from multiple clients, basically, you have 2 choices:
Still use synchronous socket I/O, but in multiple threads, each thread communicates with one client, and writes data into a shared file handle, which is protected by a mutex lock.
Use asynchronous socket I/O, single thread. In a loop, you should first call select() on multiple sockets, and do I/O once there're events on the sockets. In this case, you don't need mutex on the file handle.
Another way is to create a thread for each connection and create a file for each thread using the client-ip and port to name the file. Later you can combine these files.