Server-client file transfer using UDP in C - c

I have to make a server-client file tranfer using UDP . I have created a basic server which receives message sent by client . That's all.
Now comes the major part :-
1. The message sent by client is the name of file .
2. Now the server checks whether there exists this file or not .
3. If there exists it sends the file to the client and it also keeps the count of the number of requests of file made by the client .
I am new to this and i don't get it how to proceed further .
Here is the Server Code
#include<sys/socket.h>
#include<arpa/inet.h>
#include<stdio.h>
#include<unistd.h>
#include<fcntl.h>
#include<sys/types.h>
#include<string.h>
int main()
{
char buff[2000];
char file_buffer[2000];
int sd,connfd,len;
struct sockaddr_in servaddr,cliaddr;
sd = socket(AF_INET, SOCK_DGRAM, 0);
if(sd==-1)
{
printf(" socket not created in server\n");
exit(0);
}
else
{
printf("socket created in server\n");
}
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = INADDR_ANY;
servaddr.sin_port = htons(7802);
if ( bind(sd, (struct sockaddr *)&servaddr, sizeof(servaddr)) != 0 )
printf("Not binded\n");
else
printf("Binded\n");
len=sizeof(cliaddr);
recvfrom(sd,buff,1024,0,
(struct sockaddr *)&cliaddr, &len);
printf("%s\n",buff);
/* */
FILE *fp;
fp=fopen(buff,"r");
if(fp==NULL)
{
printf("file does not exist\n");
}
fseek(fp,0,SEEK_END);
size_t file_size=ftell(fp);
fseek(fp,0,SEEK_SET);
if(fread(file_buffer,file_size,1,fp)<=0)
{
printf("unable to copy file into buffer\n");
exit(1);
}
if(sendto(sd,file_buffer,strlen(file_buffer),0, (struct sockaddr *)&cliaddr, &len)<0) {
printf("error in sending the file\n");
exit(1);
}
bzero(file_buffer,sizeof(file_buffer));
/* */
close(sd);
return(0);
}
Here is the client code
#include <stdio.h>
#include <errno.h>
#include <sys/socket.h>
#include <resolv.h>
#include<netinet/in.h>
#include<sys/types.h>
int main()
{
char buff[2000];
int sockfd,connfd,len;
struct sockaddr_in servaddr,cliaddr;
// create socket in client side
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if(sockfd==-1)
{
printf(" socket not created in client\n");
exit(0);
}
else
{
printf("socket created in client\n");
}
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = INADDR_ANY; // ANY address or use specific address
servaddr.sin_port = htons(7802); // Port address
printf("Type ur UDP client message\n");
scanf("%s",buff);
// send msg to server
sendto(sockfd, buff, strlen(buff), 0,
(struct sockaddr *)&servaddr, sizeof(struct sockaddr));
char file_buffer[2000];
if (recvfrom(sockfd,file_buffer,2000,0, (struct sockaddr *)&servaddr, sizeof(struct sockaddr))<0)
{
printf("error in recieving the file\n");
exit(1);
}
char new_file[]="copied";
strcat(new_file,buff);
FILE *fp;
fp=fopen(new_file,"w+");
if(fwrite(file_buffer,1,sizeof(file_buffer),fp)<0)
{
printf("error writting file\n");
exit(1);
}
//close client side connection
close(sockfd);
return(0);
}
I have edited the programme and created a new buffer file_buffer , The server reads the data from file and writes into it and send to the client , On the other end client receive the data and make duplicate of this file and write into it. But on compiling it gives error in writting the file :(

You will have to extend the logic at both places. Basically for the server code, you can use the buff as the filename and check if it exists. You can use "fopen (buff, "r" )" -- if this returns NULL, then the file does not exist and in that case you might want to send the client a note saying that the file does not exist. Something like this:
FILE *istream;
strncpy(fileName, buff, ret_len + 1);
if ( (istream = fopen(fileName, "r" ) ) == NULL ){
printf ( "file non-existant!\n" );
strncpy(buff, "Does not Exist", strlen("Does Not Exist"));
} else {
printf ( "file exists!\n" );
strncpy(buff, "Does Exist", strlen("Does Exist"));
fclose (istream );
}
ret_len = sendto(sd, buff, strlen(buff), 0, (struct sockaddr *)&cliaddr, sizeof(struct sockaddr));
if (ret_len < 0) {
fprintf(stderr, "sendto() failed [ret value: %d]\n", ret_len);
return -1;
}
If the file exists, then read the file and send the content to the file.
The client must do a recvfrom() from the server after it sends the buffer to the server! Something like this. Note that you can use a numeric value (-1 or 0) to indicate if the file exists or not. And if the file exists, you can probably pass the file length in the initial message -- this way, the client would know how much data it needs to read.
// send msg to server
sendto(sockfd, buff, strlen(buff) + 1, 0, (struct sockaddr *)&servaddr, sizeof(struct sockaddr));
// recveive from server
ret_len = recvfrom(sockfd, buff, 1024, 0, NULL, 0);
printf("Received from server: %s \n",buff);
if (strncmp(buff, "Does not Exist", strlen("Does not Exist")) == 0)
printf("File does not exist\n");
else if (strncmp(buff, "Does Exist", strlen("Does Exist")) == 0)
printf("File does exist\n");
else
printf("Unknown message\n");
Btw, in the above code, we need to add 1 to account for the NUL character. Also, once this step is done, the client code should call recvfrom() in a loop to receive data from the server, as communicated in the earlier step.
Note that if the file is too big, then you probably want to read it only as much as the message you want to send -- with UDP you can send upto 64K but you should ideally send only upto 1 MUT (around 1500 bytes).

I wasn't sure if you had to develop your own client/server or if you could use others? There are a few other open source UDP based file transfer systems like UDT, UFTP, Tsunami-UDP, and even Google's QUIC.

Do you want the server to behave like a FTP server?
After receiving a filename from client, check whether it exists. See What's the best way to check if a file exists in C? (cross platform). Then open the file and send it buffer by buffer(e.g. 200 bytes at a time) to client. Simutaneously, the client receive it and write to a new file named filename.

Related

Client code is unable to read data from server [sockets]

My objective is to implement a simple data transfer from server to client. The problem is that the client is unable to read data from the server most of the time (it only works sometimes) even though the server says that the transfer was successful.
server.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#define PORT 8080
void main() {
int sock = socket(AF_INET, SOCK_STREAM, 0), option = 1;
struct sockaddr_in address;
socklen_t addrlen = sizeof(address);
char buffer[1024] = {0};
char source_file[] = "<path>/something.txt";
char fname[] = "something.txt";
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(PORT);
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &option, sizeof(option));
if(bind(sock, (struct sockaddr*) &address, sizeof(address)) == -1){
perror("Could not bind to address");
return;
}
if(listen(sock, 5) == -1) {
perror("Error while listening to connections");
return;
}
int new_socket = accept(sock, (struct sockaddr*) &address, &addrlen);
if(new_socket == -1){
perror("Error connecting to client");
exit(EXIT_FAILURE);
}
else printf("Connected to client\n");
// first send the filename
if(send(new_socket, fname, sizeof(fname), 0) == -1){
perror("Error while sending file");
return;
}
printf("Sending file %s\n\n", source_file);
FILE* f = fopen(source_file, "r");
// send the contents of the file
while(fgets(buffer, sizeof(buffer), f)){
printf("Sending %s", buffer);
if(send(new_socket, buffer, strlen(buffer), 0) == -1)
perror("Error while sending\n");
else printf("Successfully sent\n\n");
memset(buffer, 0, sizeof(buffer));
}
printf("File transfer complete\n");
fclose(f);
}
client.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#define PORT 8080
void main() {
int sock = socket(AF_INET, SOCK_STREAM, 0);
long val;
struct sockaddr_in address;
char buffer[1024] = {0};
address.sin_family = AF_INET;
address.sin_port = htons(PORT);
if(inet_pton(AF_INET, "127.0.0.1", &address.sin_addr) == -1){
perror("Invalid IP value");
exit(EXIT_FAILURE);
}
if(connect(sock,(struct sockaddr*) &address, sizeof(address)) == -1){
perror("Connection Error");
exit(EXIT_FAILURE);
}
else printf("Connected to server\n");
// Get file name from server
if(read(sock, buffer, sizeof(buffer)) == -1){
perror("Could not read filename from server");
exit(EXIT_FAILURE);
}
printf("Receiving file %s\n", buffer);
FILE *f = fopen(buffer, "w");
// printf("%ld", read(sock, buffer, sizeof(buffer)));
while((val = read(sock, buffer, sizeof(buffer)))){
if (val == 0) break;
if (val == -1) {
perror("Error reading the content");
break;
}
printf("Read returned %ld\n", val);
printf("Received %s", buffer);
fputs(buffer, f);
memset(buffer, 0, sizeof(buffer));
}
printf("File transfer complete\n");
fclose(f);
}
Sample text file for data transfer
Hello there!
Nice to meet you.
This is a text file.
Bye Bye :)
Have a good day.
Execution from server side
$ cc ./server.c -o server
$ ./server
Connected to client
Sending file /home/username/Documents/something.txt
Sending Hello there!
Successfully sent
Sending Nice to meet you.
Successfully sent
Sending This is a text file.
Successfully sent
Sending Bye Bye :)
Successfully sent
Sending Have a good day.
Successfully sent
File transfer complete
This was the output I got from the server-side. This is weird because on client-side I didn't receive any message
$ cc ./client.c -o client
$ ./client
Connected to server
Receiving file something.txt
File transfer complete
The while loop in client side did not execute at all (because the data within buffer wasn't printed) and the read function did not return -1 otherwise a proper message would have been displayed.
This exact client code only works sometimes and other times it doesn't. What's the problem here?

Client only receiving partial data back from the server via a socket in C

Brand new to StackOverflow and definitely brand new to figuring out how to get sockets to work in C. Here's what I'm trying to do: I need to create two programs where one acts as a "daemon" (not actually, you just launch it first and it runs in the background) that listens on a specified port, and then another program that attempts to send information -- via that port -- from a plaintext file, along with the name of a "key" file that should be used to encrypt it. The daemon program connects to the (let's call it client) program, forks off a new process, accepts the information, encrypts the text accordingly, and then sends it back to the client program to be stored in a file.
This last part is where I'm having trouble. I've been able to successfully transfer all of the data from the client to the daemon program, and even successfully encrypt it; I tried storing the info into a temp file to see how it was coming out and everything looked as it should. But when I try to send the information back -- it's worth noting that I'm trying to send it back in chunks as the daemon program is encrypting it and therefore potentially still receiving info -- the client only receives a fraction of the data before the connection is seemingly closed and the process is finished.
Sorry for the lengthy post, just trying to be as detailed as possible. I tried searching for some posts regarding this topic and I did find this one, but it wasn't quite the same issue (plus the suggested fixes were things I already tried). Below is what I think is the pertinent code. This is only my current set up, so certain aspects might just be random bits from different approaches I've tried, e.g. the shutdown on write on the client side is a recent addition that doesn't appear to have made a difference. I've tried a number of different things to make this work over the past week, so if any of the suggestions that come in are things that I've tried, I'll let you folks know. Thanks in advance!
Client:
//Create socket, check for success
//
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd == -1){
fprintf(stderr, "socket creation failed");
exit(1);
}
//Create address structure for socket to connect to
struct sockaddr_in server;
server.sin_family = AF_INET;
server.sin_port = htons(port);
server.sin_addr.s_addr = INADDR_ANY;
int success;
success = connect(sockfd, (struct sockaddr*) &server, sizeof(server));
if(success == -1){
fprintf(stderr, "Could not find port, failed to connect socket\n");
exit(2);
}
//IF all is well, open up the plaintext file for extracting data
FILE* ptextSend = fopen(argv[1], "r");
int totalNeeded;
rewind(ptextSend);
fseek(ptextSend, 0L, SEEK_END);
totalNeeded = ftell(ptextSend);
totalNeeded = totalNeeded - 1;
rewind(ptextSend);
//First, send key path
send(sockfd, keypath, sizeof(keypath), 0);
//Then, send contents of file
int n = 0;
char buffer[1000];
while(n < totalNeeded){
fgets(buffer, 1000, ptextSend);
printf("right now buffer is %s\n", buffer);
n = n + (send(sockfd, buffer, sizeof(buffer), 0));
}
shutdown(sockfd, 1);
//Attempt to receive encrypted info back
n=1;
while(n != 0){
char* newBuff[1000];
n = recv(sockfd, newBuff, sizeof(newBuff) - 1, 0);
if(n!=0)
fprintf(stdout, "this is the client: %s\n", newBuff);
}
Daemon/Server code:
//Create socket
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd == -1){
fprintf(stderr, "Server error: failure to create socket.\n");
exit(1);
}
//Create address for socket
struct sockaddr_in server;
server.sin_family = AF_INET;
server.sin_port = htons(port);
server.sin_addr.s_addr = INADDR_ANY;
//Bind socket to port using address struct
int bindSuccess = bind(sockfd, (struct sockaddr*) &server, sizeof(server));
if(bindSuccess == -1){
fprintf(stderr, "Server error: bind call failed.\n");
exit(1);
}
//Set socket to listen
int listenSuccess = listen(sockfd, 5);
if(listenSuccess == -1){
fprintf(stderr, "Server error: listen call failed.\n");
exit(1);
}
//Accept next client connection
struct sockaddr_in client_addr;
socklen_t client_length = sizeof(client_addr);
int client_sockfd = accept(sockfd, (struct sockaddr*) &client_addr, &client_length);
if(client_sockfd == -1){
fprintf(stderr, "Server error: accept call failed.\n");
exit(1);
}
pid_t pid = fork();
if(pid < 0){
fprintf(stderr, "Error forking process on connection.\n");
exit(1);
}
if(pid == 0){
//First receive key path
char keybuff[100];
recv(client_sockfd, keybuff, sizeof(keybuff),0);
FILE* theKey = fopen(keybuff, "r");
char buffer[1000];
int n = 1;
while(n != 0){
n = recv(client_sockfd, buffer, sizeof(buffer) - 1, 0);
strtok(buffer, "\n");
char* newString = encrypt(buffer, theKey);
send(client_sockfd, newString, sizeof(newString) - 1, 0);
}
if(n == -1){
fprintf(stderr, "Server error: failed to read from socket.\n");
exit(1);
}
fclose(theKey);
close(client_sockfd);
close(sockfd);
return 0;
}else
return 0;
}
What I should be getting back is "right now buffer is: THE RED GOOSE FLIES AT MIDNIGHT STOP" followed by its encrypted version, so 36 characters of gibberish (occasionally broken up with "this is the client" and a newline). Instead, the total output is:
right now buffer is THE RED GOOSE FLIES AT MIDNIGHT STOP
this is the client: BPZDOSZ
...so just seven characters worth of data and then it exits (successfully).

Read a text file on server side which is sent from client side using C

I want to send one text file from client side and want to read the text file on the server side and want to display the texts on the server terminal screen. I have successfully written code for both server and multiple client. I have also sent a text file from client to server side. But now I want to know how to modify the text file and send it and read the text file on server end which is sent from the client side. My server and client code is given below together:
Server and Client Code:
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdint.h>
#include <stdlib.h>
#include <pthread.h>
#define filename "//home//myname//Documents//folder1//folder2//input.txt"
#define MAX_CLIENTS 5
//the thread function
void *new_connection_handler(void *);
int main(int argc , char *argv[])
{
//client variables
int sock;
struct sockaddr_in server;
char buffer[256], server_reply[2000];
int len;
//server variables
int socket_desc , client_sock;
struct sockaddr_in client;
socklen_t c = sizeof(client);
//check if the the command contain less than two arguments
if(argc != 2)
{
printf("use either: %s <server/client>\n", argv[0]);
}
// If the command contains minumum 2 arguments
else{
// If argv is client then execute the client code
if(strcmp("client",argv[1]) == 0)
{
/****************/// Client code here **********************************************************************
//Create socket
sock = socket(AF_INET , SOCK_STREAM , 0);
if (sock == -1)
{
printf("Could not create socket");
}
puts("Socket created");
server.sin_addr.s_addr = inet_addr("127.0.0.1");
server.sin_family = AF_INET;
server.sin_port = htons( 8888 );
//Connect to remote server
if (connect(sock , (struct sockaddr *)&server , sizeof(server)) < 0)
{
perror("connect failed. Error");
return 1;
}
puts("Connected\n");
//keep communicating with server
/* Time to send the file */
/******************************************************/
FILE *pf;
int fsize;
pf = fopen(filename, "rb");
if (pf == NULL)
{
printf("File not found!\n");
return 1;
}
else
{
printf("Found file %s\n", filename);
fseek(pf, 0, SEEK_END);
fsize = ftell(pf);
rewind(pf);
printf("File contains %ld bytes!\n", fsize);
printf("Sending the file now\n");
}
while (1)
{
// Read data into buffer. We may not have enough to fill up buffer, so we
// store how many bytes were actually read in bytes_read.
int bytes_read = fread(buffer, sizeof(buffer), 1, pf);
if (bytes_read == 0) // We're done reading from the file
break;
if (bytes_read < 0)
{
error("ERROR reading from file\n");
}
while (bytes_read > 0)
{
int bytes_written = write(sock, buffer, bytes_read);
if (bytes_written <= 0)
{
error("ERROR writing to socket\n");
}
}
}
printf("Done Sending the File!\n");
printf("Now Closing Connection.\n");
/*********************************************************************************/
close(sock);
}
/****************/// Server code here **********************************************************************
// If argv is server then execute the server code
if(strcmp("server", argv[1]) == 0 )
{
//Create socket
socket_desc = socket(AF_INET , SOCK_STREAM , 0);
if (socket_desc == -1)
{
printf("Could not create socket");
}
//Prepare the sockaddr_in structure
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons( 8888 );
bzero (&server.sin_zero, 8);
//Bind
if( bind(socket_desc,(struct sockaddr *)&server , sizeof(server)) < 0)
{
//print the error message
perror("bind failed. Error");
return 1;
}
//Listen
listen(socket_desc , MAX_CLIENTS);
//Accept and incoming connection
printf("Waiting for incoming connections\n");
c = sizeof(client);
while( (client_sock = accept(socket_desc, (struct sockaddr *)&client, &c)) )
{
printf("Connection accepted\n");
pthread_t thread_id;
if( pthread_create( &thread_id , NULL , new_connection_handler , (void*) (intptr_t)client_sock) < 0)
{
perror("could not create thread");
return 1;
}
printf("Handler assigned\n");
}
if (client_sock < 0)
{
perror("accept failed");
return 1;
}
}
}
return 0;
}
void *new_connection_handler(void *socket_desc)
{
//Get the socket descriptor
int sock = (intptr_t)socket_desc;
int read_size = 0;
char client_message[2000];
//PROBLEM **read the text file sent from client side and display the text on screen**
while( (read_size = recv(sock , client_message , sizeof(client_message) , 0)) > 0 )
printf("Read Text: %.*s", read_size, client_message);
if(read_size == 0)
{
printf("Client disconnected\n");
fflush(stdout);
}
else if(read_size == -1)
{
perror("recv failed");
}
return 0;
}
You had done some mistakes in your code.
int bytes_read = fread(buffer, sizeof(buffer), 1 ,pf);
This statement is wrong, when you print the bytes_read value it print 1 has a result.If you pass this to next while it will print the h repeatedly.
Use this below statement instead of that fread:
int bytes_read = fread(buffer, 1, sizeof(buffer), pf);
This statement only returns the correct readed value.
while (bytes_read > 0)
{
int bytes_written = write(sock, buffer, bytes_read);
if (bytes_written <= 0)
{
error("ERROR writing to socket\n");
}
}
In this part of the code your program writing the readed content again and again into the socket without break, so the server is print the text without break.
So use this statement after the write() bytes_read=bytes_read-bytes_written; if the read buffer is fully written in your socket it break the statement.
And one more thing is always try to use long data type, when you are trying to use file, because int has lower range compared to long.
UPDATE:
Put the fread(buffer, 1, sizeof(buffer), pf); and try it. It will work.
You can use open() or fopen().
fd=open("filename",O_RDWR);
fd - returns descriptor of the opened file.
O_RDWR - which is used to open file for read and write, you must include fcntl.h.
fp=fopen("filename","r+");
fp - File pointer.
rw - Opened file for both read and write.
File content:
Chandru
ttttt.
After replace:
Stackoverflowt.
Here the content is big so the content is overwritten in the another line.
To avoid that you need to write the changed content in another file.
Writing in another file would be easy to append the text in the line end.

return from read in connected udp sockets in c

i programming UDP client/Server model and the main functionaly for this app is client insert the directory path then the server will retrun the contents of supplied directory to the client, so this Client code :
#include "cliHeader_UDP.h"
int
main(int argc, char **argv)
{
int sockfd;
struct sockaddr_in servaddr;
/*Error checking for providing appropirate port# */
if(argc<3 )
err_quit("Error,no port provided, please enter the port#:22011 \n");
portno=atoi(argv[2]);
for(;;)
{
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(portno);
Inet_pton(AF_INET, argv[1], &servaddr.sin_addr);
sockfd = Socket(AF_INET, SOCK_DGRAM, 0);
dg_cli(stdin, sockfd, (SA *) &servaddr, sizeof(servaddr));
}
exit(0);
}
**//and here is the dg_cli implemntation :**
void
dg_cli(FILE *fp, int sockfd, const SA *pservaddr, socklen_t servlen)
{
int n;
char sendline[MAXLINE], recvline[MAXLINE + 1];
Connect(sockfd, (SA *) pservaddr, servlen);
for(;;)
{
bzero(&sendline, sizeof(sendline));
printf("please enter Directory Name :\n");
Fgets(sendline, MAXLINE, fp);
/*To check if the supplied name ended with \n in sendline buffer */
if((p = strchr(sendline, '\n'))) *p = 0;
write(sockfd, sendline, strlen(sendline));
printf("test for write\n");
**Line 31.......:** while ( (n=read(sockfd, recvline, MAXLINE)) )
{
if(n<0)
perror("Error");
printf("recvline is: %s\n",recvline);
printf("n========%d\n",n);
}
printf("exit from read While\n");
recvline[n] = 0; /* null terminate */
}
}
the problem in Line 31... is the 1st time run as i wanted client insert DIR path so the server will return the contents of the path ,but when the user need to insert again the path ,its still blocking in read in the for loop and does not return from for loop ,
so how to put condtion when the contents of buffer ended return from for loop like EOF in TCP
As you noticed there's no concept of "connection" in UDP - even if you called connect(2) - so there's no way for read to return 0 when the communication is over. There are ways to fix this:
Have the server send a 0-length message when the output is over or some other special marker
Have the client analyze the input and somehow detect it is over
Both these methods are a little bit fragile in practice: imagine what happens if the "output is over" message gets lots. So you'll also have to provision for that case and maybe add a timeout (look for SO_RCVTIMEO for example).
i tried some thing like that have a look :
part of code at server side:
//at server side Read the directory contents
printf("The contents of [%s] is :\n",mesg);
bzero(&mesg, sizeof(mesg));
while( (dptr = readdir(dp)) !=NULL )
{
printf(" \n[%s] \t",dptr->d_name);
//report(dptr->d_name, &status_buf);
sprintf(mesg,"%s",dptr->d_name);
if((dptr = readdir(dp)) ==NULL)
{
bzero(&mesg, sizeof(mesg));
sprintf(mesg,"%c",'!');
Sendto(sockfd, mesg, sizeof(mesg), 0, pcliaddr, len);
}
Sendto(sockfd, mesg, sizeof(mesg), 0, pcliaddr, len);
}
// Close the directory stream
closedir(dp);
//and at the client side :
flag=1;
while ( (n=read(sockfd, recvline, MAXLINE)) )
{
if(n<0)
perror("Error");
printf("recvline is: %s\n",recvline);
flag=flag+1;
printf("Flag now is :%d\n",flag);
printf("n========%d\n",n);
bzero(&recvline, sizeof(recvline));
if(recvline[0]=='!')
return;
}

UDP client unable to receive data from the server

I have a UDP client and a UDP server. The flow of the program is: first the server is executed from the terminal, the terminal creates a socket and binds it and waits for a filename from the client. In another terminal the client is executed. Here also a socket is created, and a connection is established with the server. Then a filename is provided to the client. This filename is sent to the server using sendto() function. The server is able to receive filename from the client and the server is also sending the data in the file to the client. However the receiver on the other side keeps waiting for the data from the server.
The code for the UDP client and server is as shown below.
UDP Server:
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<sys/stat.h>
#include<unistd.h>
#include<stdlib.h>
#include<stdio.h>
#include<fcntl.h>
int main()
{
int cont,create_socket,new_socket,addrlen,fd;
int bufsize = 1024;
int nameLen=0;
int client_address_size=0;
char *buffer = malloc(10);
char fname[256];
struct sockaddr_in address,client;
if ((create_socket = socket(AF_INET,SOCK_DGRAM,0)) > 0)
printf("The socket was created\n");
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(15000);
if (bind(create_socket,(struct sockaddr *)&address,sizeof(address))== 0)
printf("Binding Socket\n");
nameLen=sizeof(address);
if (getsockname(create_socket,(struct sockaddr *)&address,&nameLen)<0)
{
printf("\n\ngetsockname() error\n");
exit(3);
}
printf("Port assigned is %d\n", ntohs(address.sin_port));
client_address_size=sizeof(client);
if(recvfrom(create_socket,fname, 255,0,(struct sockaddr *) &client,&client_address_size)<0)
{
printf("\n\nrecvfrom() failed\n");
exit(4);
}
printf("A request for filename %s Received..\n", fname);
if ((fd=open(fname, O_RDONLY))<0)
{
perror("File Open Failed");
exit(0);
}
while((cont=read(fd, buffer, 10))>0)
{
//sleep(1);
sendto(create_socket,buffer,cont,0,(struct sockaddr *) &client,&client_address_size);
printf("\n\nPacket sent\n");
}
printf("Request Completed\n");
return close(create_socket);
}
UDP Client:
#include<sys/socket.h>
#include<sys/types.h>
#include<netinet/in.h>
#include<unistd.h>
#include<stdlib.h>
#include<stdio.h>
int main()
{
int create_socket,cont;
char *arg="127.0.0.1";
int bufsize = 1024;
int server_address_size=0;
char *buffer = malloc(10);
char fname[256];
struct sockaddr_in address,server;
if ((create_socket = socket(AF_INET,SOCK_DGRAM,0)) > 0)
printf("The Socket was created\n");
address.sin_family = AF_INET;
address.sin_port = htons(15000);
address.sin_addr.s_addr=inet_addr(arg);
if (connect(create_socket,(struct sockaddr *) &address,sizeof(address)) == 0)
printf("The connection was accepted with the server %s...\n",arg);
printf("Enter The Filename to Request : ");
scanf("%s",fname);
sendto(create_socket, fname, sizeof(fname), 0,(struct sockaddr *) &address,sizeof(address));
printf("Request Accepted... Receiving File...\n\n");
server_address_size=sizeof(server);
printf("The contents of file are...\n\n");
while((cont=recvfrom(create_socket, buffer, 10, 0,(struct sockaddr *) &address,sizeof(address)))>0)
{
write(1, buffer, cont);
}
printf("\nEOF\n");
return close(create_socket);
}
Where am i going wrong? Please provide a proper solution for the same.
Thanks in advance.
You are using the value-result arguments in recvfrom() wrong. A compiler should warn you about this very loudly. Recvfrom() will try to return a number to you in the 6th parameter, so you can not pass it a constant created with sizeof().
From the manpage:
The argument addrlen is a
value-result argument, which the caller should initialize before the call to the
size of the buffer associated with src_addr, and modified on return to indicate the
actual size of the source address.
I changed the recvfrom() loop like this and a file was successfully sent & received.
int serv_addr_size = sizeof(address);
while((cont=recvfrom(create_socket, buffer, 10, 0,(struct sockaddr *) &address,&serv_addr_size))>0)
{
write(1, buffer, cont);
}
Since you are calling connect() on the socket, you could also use recv(), like so:
recv(create_socket, buffer, 10, 0)
As some general advice, allways carefully check the return values from system and library calls (except maybe for printf()) and be prepared for all cases listed on the functions man-page under "return values".
EDIT The server side makes a similar error in the other direction. A parameter of sendto() that should just be the length of the passed struct, is passed as a pointer.
sendto(create_socket,buffer,cont,0,(struct sockaddr *) &client,&client_address_size);
Should be
sendto(create_socket,buffer,cont,0,(struct sockaddr *) &client,client_address_size);
Just let me to write a valid example. I've tried to rewrite your own code, but I prefer to show you a nice example. Just a few minutes...
---EDIT---
Ok, here I am. Forgive me for the time I spent, but I preferred to read carefully the code.
Here your two files:
Server implementation
Client implementation
Really hope I helped you.

Resources