UDP client unable to receive data from the server - c

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.

Related

Sockets Programming Program received signal SIGSEGV, Segmentation fault

I am trying to create a file transfer program using pthread.h in regards to sockets programming using C.
Both the client and the server source code are implemented but when I run the program it reports "Segmentation fault (core dumped)".
I tried running the program with gdb and it gives me the following error when I input a given file for transfer from the client-side.
Program received signal SIGSEGV, Segmentation fault.
__strcat_sse2_unaligned ()
at ../sysdeps/x86_64/multiarch/strcpy-sse2-unaligned.S:298
298 ../sysdeps/x86_64/multiarch/strcpy-sse2-unaligned.S: No such file or directory.
Here is the client source code:
#include<netinet/in.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include <unistd.h>
#include <arpa/inet.h>
#define SERVER_PORT 8000
#define BUFFER_SIZE 1024
#define FILE_PATH_SIZE 1024
void find_file_name(char *name, char *path);
int main()
{
struct sockaddr_in client_addr;
bzero(&client_addr, sizeof(client_addr));
client_addr.sin_family = AF_INET;
client_addr.sin_addr.s_addr = htons(INADDR_ANY);
client_addr.sin_port = htons(0);
int client_socket_fd = socket(AF_INET, SOCK_STREAM, 0);
if (client_socket_fd < 0)
{
perror("Create Socket Failed:");
exit(1);
}
else {
perror("Create Socket Done:");
}
if (-1 == (bind(client_socket_fd, (struct sockaddr*)&client_addr, sizeof(client_addr))))
{
perror("Client Bind Failed:");
exit(1);
}
else {
perror("Client Bind Success:");
}
//////////////////////////////////////////////////////////////////////////////////////////////////////
// Declare a socket address structure on the server side, and initialize it with the IP address and port on the server side for subsequent connections
struct sockaddr_in server_addr;
bzero(&server_addr, sizeof(server_addr));
server_addr.sin_family = AF_INET;
//Convert the dotted decimal string into a network byte order binary value. This function can handle both IPv4 and IPv6 addresses.
// The first parameter can be AF_INET or AF_INET6:
// The second parameter is a pointer to a dotted decimal string:
// The third parameter is a pointer to the binary value of the converted network byte order.
if (inet_pton(AF_INET, "127.0.0.1", &server_addr.sin_addr) == 0)
{
perror("Server IP Address Error:");
exit(1);
}
else {
perror("Server IP Address Success:");
}
server_addr.sin_port = htons(SERVER_PORT);
socklen_t server_addr_length = sizeof(server_addr);
// int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
// sockfd: the first parameter is the socket descriptor of the client
// addr: the local address of the current client, a variable of type struct sockaddr_un, a variable of type struct sockaddr_in in different hosts,
// addrlen: indicates the byte length of the local address
// Return value: success flag
if (connect(client_socket_fd, (struct sockaddr*)&server_addr, server_addr_length) < 0)
{
perror("Can Not Connect To Server IP:");
exit(0);
}
else {
perror("Connected to the Server IP:");
}
char file_path[FILE_PATH_SIZE + 1];
bzero(file_path, FILE_PATH_SIZE + 1);
printf("Input the File Path on Server:\t");
scanf("%s", file_path);
char buffer[BUFFER_SIZE];
bzero(buffer, BUFFER_SIZE);
strncpy(buffer, file_path, strlen(file_path)>BUFFER_SIZE ? BUFFER_SIZE : strlen(file_path));
//ssize_t send(int sockfd, const void *buf, size_t len, int flags);
//socket: If it is a server, it is the return value of accpet() function, the client is the first parameter in connect() function
// buffer: data written or read
// len: size of data written or read
if (send(client_socket_fd, buffer, BUFFER_SIZE, 0) < 0)
{
perror("Send File Name Failed:");
exit(1);
}
//Convert the target path to a local storage path
char save_path[FILE_PATH_SIZE + 1] = {"/home/madaskalas/Desktop/sockets/pthread/client_files"};
find_file_name(file_path, save_path);
//Try to open the file
FILE *fp = fopen(save_path, "w");
if (NULL == fp)
{
printf("File:\t%s Can Not Open To Write\n", save_path);
exit(1);
}
// Receive data from the server to the buffer
// Each time a piece of data is received, it will be written to the file, looping until the file is received and written
bzero(buffer, BUFFER_SIZE);
int length = 0;
while ((length = recv(client_socket_fd, buffer, BUFFER_SIZE, 0)) > 0)
{
if (fwrite(buffer, sizeof(char), length, fp) < length)
{
printf("File:\t%s Write Failed\n", save_path);
break;
}
bzero(buffer, BUFFER_SIZE);
}
// After receiving successfully, close the file and close the socket
printf("Receive File:\t%s From Server IP Successful!\n",save_path);
// close(fp);
close(client_socket_fd);
return 0;
}
void find_file_name(char *name, char *path)
{
char *name_start = NULL;
int sep = '/';
if (NULL == name) {
printf("the path name is NULL\n");
// return NULL;
}
name_start = strrchr(name, sep);
if (NULL == name_start)
{
strcat(path, name_start);
}
else
strcat(path, name_start + 1);
}
Here is the server source code:
#include<stdlib.h>
#include<pthread.h>
#include<netinet/in.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<arpa/inet.h>
#include <unistd.h>
#define SERVER_PORT 8000
#define LENGTH_OF_LISTEN_QUEUE 20
#define BUFFER_SIZE 1024
#define FILE_NAME_MAX_SIZE 1024
static void Data_handle(void * sock_fd);
int main(void)
{
////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Declare and initialize a server-side socket address structure, socketaddr_in is the address form of the socket in the internet environment
//sockaddr_in (defined in netinet/in.h):
// struct sockaddr_in {
// short int sin_family; /* Address family */
// unsigned short int sin_port; /* Port number */
// struct in_addr sin_addr; /* Internet address */
// unsigned char sin_zero[8]; /* Same size as struct sockaddr */
//};
//struct in_addr {unsigned long s_addr;};
struct sockaddr_in server_addr;
bzero(&server_addr, sizeof(server_addr));
//Sa_family: It is an address family, also a masterpiece, a protocol family, generally in the form of "AF_XXX", commonly used are
//AF_INET Arpa (TCP/IP) network communication protocol
//AF_UNIX UNIX domain protocol (file system socket)
//AF_ISO ISO standard protocol
//AF_NS Xerox Network System Agreement
//AF_IPX Novell IPX protocol
//AF_APPLETALK Appletalk DDS
server_addr.sin_family = AF_INET;
//htons is to convert integer variables from host byte order to network byte order, that is, the integer storage method in the address space becomes the high-order byte and is stored at the low address of the memory.
//INADDR_ANY: 0.0.0.0, which refers to the meaning of this machine, that is, it means all the IP of this machine, monitor all the network cards of this machine
server_addr.sin_addr.s_addr = htons(INADDR_ANY);
server_addr.sin_port = htons(SERVER_PORT);
////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Create socket, if successful, return socket descriptor
//1, domain: the protocol domain, also known as the protocol family (family). AF_INET: TCP/IP protocol cluster
//2, type: Specify the socket type. SOCK_STREAM (commonly used) byte stream socket
//3, protocol: As the name implies, it is to specify the protocol. 0: IPPROTO_TCP TCP transmission protocol
int server_socket_fd = socket(PF_INET, SOCK_STREAM, 0);
if(server_socket_fd < 0)
{
perror("Create Socket Failed:");
exit(1);
}
else {
perror("Create Socket Done:");
}
//int getsockopt(int sock, int level, int optname, void *optval, socklen_t *optlen);
//sock: The socket that will be set or get options. level: The protocol layer where the option is located.
//optname: The name of the option to be accessed. optval: For getsockopt(), points to the buffer that returns the option value. optlen: The maximum length of the option value when used as an entry parameter.
// Let SO_REUSEADD==true allow the socket to be bound to an address already in use (see bind()).
int opt = 1;
setsockopt(server_socket_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
//bind binds socket and socket address structure
//The three parameters are: socket descriptor, protocol address, and the length of the address
if(-1 == (bind(server_socket_fd, (struct sockaddr*)&server_addr, sizeof(server_addr))))
{
perror("Server Bind Failed:");
exit(1);
}
else {
perror("Server Bind Success:");
}
//sockfd: The first parameter is the socket descriptor to be monitored
//backlog: The second parameter is the maximum number of connections that the corresponding socket can queue
//The socket created by the socket() function is an active type by default, and the listen function changes the socket to a passive type, waiting for the client's connection request.
if(-1 == (listen(server_socket_fd, LENGTH_OF_LISTEN_QUEUE)))
{
perror("Server Listen Failed:");
exit(1);
}
printf("Socket Listen Successful! Begin to listen!\n");
///////////////////////////////////////////////////////////////////////////////////////////////////////////
while(1)
{
// Define the client's socket address structure
struct sockaddr_in client_addr;
socklen_t client_addr_length = sizeof(client_addr);
//int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
//sockfd: The first parameter is the socket descriptor of the server
//addr:, the second parameter is a pointer to struct sockaddr *, used to return the client's protocol address
//addrlen: The third parameter is the length of the protocol address
//Return value: If accpet succeeds, the return value is a brand new description word automatically generated by the kernel, which represents the TCP connection with the returning client.
// Accept the connection request and return a new socket (descriptor). This new socket is used to communicate with the connected client
// The accept function will write the client information to client_addr
int session_fd = accept(server_socket_fd, (struct sockaddr*)&client_addr, &client_addr_length);
if(session_fd < 0)
{
perror("Server Accept Failed:");
// break;
}
else {
perror("Server Accept Success:");
}
char client_addr_res[20];
//char *ptr=inet_ntop(AF_INET, &client_addr.sin_addr, client_addr_res, strlen(client_addr_res));
printf("Get Connected with Client:%s ,Opening a new Thread...\n",inet_ntoa(client_addr.sin_addr) );
pthread_t thread_id;
if (pthread_create(&thread_id, NULL, (void *)(&Data_handle), (void *)(&session_fd)) == -1)
{
fprintf(stderr, "pthread_create error!\n");
break; //break while loop
}
}
// Close the socket for monitoring
close(server_socket_fd);
return 0;
}
static void Data_handle(void * fd)
{
int session_fd = *((int *)fd);
// The recv function reads the data into the byte stream through the description word and stores it in the address string
char buffer[BUFFER_SIZE];
bzero(buffer, BUFFER_SIZE);
if (recv(session_fd, buffer, BUFFER_SIZE, 0) < 0)
{
perror("Server Recieve Data Failed:");
}
char file_name[FILE_NAME_MAX_SIZE + 1];
bzero(file_name, FILE_NAME_MAX_SIZE + 1);
strncpy(file_name, buffer, strlen(buffer)>FILE_NAME_MAX_SIZE ? FILE_NAME_MAX_SIZE : strlen(buffer));
printf("Received Filename Successful\n");
// Open the file to read the data and transfer it to the connected client by the file name
FILE *fp = fopen(file_name, "r");
if (NULL == fp)
{
printf("File:%s Not Found\n", file_name);
}
else
{
bzero(buffer, BUFFER_SIZE);//Empty the buffer
int length = 0;
//Read one BUFFER_SIZE data at a time and send it to the client
while ((length = fread(buffer, sizeof(char), BUFFER_SIZE, fp)) > 0)
{
//ssize_t send(int sockfd, const void *buf, size_t len, int flags);
//socket: If it is a server, it is the return value of the accpet() function, and the client is the first parameter in the connect() function
// buffer: data written or read
// len: size of data written or read
if (send(session_fd, buffer, length, 0) < 0)
{
printf("Send File:%s Failed./n", file_name);
break;
}
bzero(buffer, BUFFER_SIZE);
}
fclose(fp);
printf("Send File:%s To Client Successful!\n", file_name);
}
// int close(int fd) fd: the first parameter of the client's connect() function, the return value of the server's accept()
close(session_fd);
pthread_exit(NULL); //terminate calling thread!
}
Compilation:
gcc -o pthread_client pthread_client.c
gcc -o pthread_server pthread_server.c
I compiled with -g and then use gdb with bt and it produces the following error.
Program received signal SIGSEGV, Segmentation fault. __strcat_sse2_unaligned () at ../sysdeps/x86_64/multiarch/strcpy-sse2-unaligned.S:298 298 ../sysdeps/x86_64/multiarch/strcpy-sse2-unaligned.S: No such file or directory. (gdb) bt #0 __strcat_sse2_unaligned () at ../sysdeps/x86_64/multiarch/strcpy-sse2-unaligned.S:298 #1 0x00005555555558b8 in find_file_name (name=0x7fffffffd440 "b.txt", path=0x7fffffffd850 "/home/madaskalas/Desktop/sockets/pthread/client_files") at pthread_client.c:138 #2 0x00005555555556fe in main () at pthread_client.c:96 –
Any help or guidance is greatly appreciated!
Do not cast to/from void*. It happens implicitly.
void Data_handle(void*); pthread_create(..., (void *)(&Data_handle), ...) is plain invalid. Data_handle should return a void*, not void. Calling a void (void*) function via void *(*)(void*) function pointer is invalid.
in server, int session_fd is a local variable inside while(1) block, yet it is passed by pointer to a thread pthread_create(, ... &session_fd) and then thread *((int *)fd); dereferences it. There is a race condition, that session_fd stops existing on the end of loop. Either use dynamic allocation, create a synchronization point to make sure it is dereferenced, or just cast it to/from uintptr_t and pass by value as the void* pointer.
why that bzero all the time? Remove all the calls to bzero maybe except for sockaddr_in initialization. Consider using = {0} there anyway.
strncpy(dest, src, strlen(src) > sizeof(dest) ? sizeof(dest) : strlen(src)) - the strlen(src) > .... is just pointless, cause then the string will not be zero terminated. Also, strncpy does copy up until zero terminating character anyway, it's not memcpy, so why check if yourself anyway. Research strlcpy and strncpy difference, and just use strlcpy(dest, src, sizeof(dest)) to copy a string anyway. Read NOTES section in strncpy man page.
if (NULL == name_start) { strcat(path, name_start); - it's invalid to copy from NULL...
You use strange additional braces in if (-1 == (function())). The ))) are very hard for humans to read in my experience. Consider using if (-1 == function()).
Instead of *((int *)fd) just *(int *)fd.
Try not to do self-explanatory comments.
Overall your code is bad and is filled with bugs and edge cases. Consider rewriting it from scratch and re-studying your material. Interest yourself in helpful code helpers - like -Wall -Wextra -fsanitize=address warnings gcc options, code linters and formatters and valgrind.

Why is Connect() returning a negative value?

#include<io.h>
#include<stdio.h>
#include<winsock2.h>
#include <ctype.h>
#include<string.h>
#include<strings.h>
#define MY_PORT 8989 //defining the port for the socket
#define MAXBUF 256
int main(int argc , char *argv[])
{
//char str[MAXBUF];
int a;
WSADATA wsa;
SOCKET sockfd , clientfd; //SOCKET is a data type. We initialize two variables of the data type Socket here
struct sockaddr_in self; //structure for the family,port and IP address of the socket (Socket descriptors)
char buffer[MAXBUF]; // this is a character array that will receive the message from the client and we will use this to manipulate
//char message[MAXBUF];
printf("\nInitialising Winsock...");
if (WSAStartup(MAKEWORD(2,2),&wsa) != 0) //WSASTARUP is used to tell windows to get ready for a connection and if it returns a value 0, windows is ready
{
printf("Failed. Error Code : %d",WSAGetLastError());
return 1;
}
printf("Initialised.\n");
/*---create streaming socket---*/
if ( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0 ) //socket is created using a function called socket
//using AF_INET means that we are using TCP/IP family
//the if statement here checks whether or not the value returned by the socket is negative or not. If it is negative that means there is some sort of an error
{
perror("Socket");
exit(errno);
}
printf("Socket created.\n");
self.sin_family = AF_INET;
self.sin_port = htons(MY_PORT);
self.sin_addr.s_addr = htonl(INADDR_ANY);
memset(&self,'\0', sizeof(self));
/*The connect function below is used to establish a connection between the client and the server*/
if (connect(sockfd, (struct sockaddr*)&self, sizeof(self)) <0)
{
printf("connection with the server failed...\n");
exit(0);
}
else
printf("connected to the server..\n");
printf("Please enter message: ");
memset(buffer, 0, sizeof (buffer));
fgets(buffer, MAXBUF, stdin); //fgets is used here to get whatever is inside the buffer
while (1)
{
/*struct sockaddr_in client_addr;
int addrlen=sizeof(client_addr);*/
/*---accept a connection (creating a data pipe)---*/
a= write(sockfd, buffer, sizeof(buffer));
if(a<0){
printf("Error");
}
// a= recv(clientfd, buffer, MAXBUF, 0);
//accept(clientfd, (struct sockaddr*)&client_addr, &addrlen);
a= read(sockfd, buffer, sizeof(buffer));
if(a<0){
printf("Error");
}
if (strncmp("QUIT", buffer, 4) == 0) {
printf("Server Exit...\n");
break;
}
}
close(sockfd); //close the sockfd
WSACleanup(); // windows socket is cleaned up
return 0;
}
The code works completely fine but for some reason, which I can't wrap my head around the connect function keeps on returning a negative value, or at least a value that is not zero. The server I am using with this client works for other clients, so I know for a fact that there is nothing wrong with it.
Your help will be much appreciated.
self.sin_family = AF_INET;
self.sin_port = htons(MY_PORT);
self.sin_addr.s_addr = htonl(INADDR_ANY);
memset(&self,'\0', sizeof(self));
In this code you set all the values of self and then you just clear self with memset. I'm pretty sure that this makes no sense and likely is the cause of the error you see, i.e. no useful parameters given for connect.
Even without this erroneous memset the code does not make much sense: you are trying to connect to INADDR_ANY but there is no such IP address to connect to. INADDR_ANY means on the server side to listen on every address of the machine - on the client side it cannot be used but instead the real IP address have to be used, like 127.0.0.1 for localhost.

Server-client file transfer using UDP in 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.

Running UDP client and server in different machines

I have a UDP client and a server running fine when run on the same computer. (Here for the client i have given 127.0.0.1 as the destination IP on the UDP client).
However when run on different machines, and replacing 127.0.0.1 with my the ip of the machine where server.c is present, the program doesnt work. The problem is i'm not getting any error message.
Below is the code for server and client. Please tell me any modifications to be performed to run the same over different machines(I'm using LINUX OS).
Note: My machines serverIP(machine where server.c is present): 10.60.5.945,
clientIP: 10.60.5.950
server.c:
#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");
}
sendto(create_socket,"*",1,0,(struct sockaddr *) &client,client_address_size);
printf("Request Completed\n");
return close(create_socket);
}
client.c:
#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,res;
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;
int serv_addr_size = sizeof(address);
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);
res=sendto(create_socket, fname, sizeof(fname), 0,(struct sockaddr *) &address,sizeof(address));
if(res<0)
{
printf("\n\nSendto falied...\n");
exit(0);
}
printf("Request Accepted... Receiving File...\n\n");
server_address_size=sizeof(address);
printf("The contents of file are...\n\n");
while((cont=recvfrom(create_socket, buffer, 10, 0,(struct sockaddr *) &address,&serv_addr_size))>0)
{
if(buffer[cont-1]=='*')
break;
write(1, buffer, cont);
}
printf("\nEOF\n");
return close(create_socket);
}
Above is the code working fine when it is run on the same system. Please tell me the modifications to be made to run the above code on different machines. Thanks in advance.
Have you tried changing char *arg="127.0.0.1"; to the servers IP address? The IP address 10.60.5.945mentioned in your question, is not a valid IP.
Even better would be to take the IP (or even a hostname that you resolve) from argv[1].
ps. You can see the valid IPv4 addresses of your Linux box by typing: ip -4 a l scope global

UDP Socket Programming in C: 2 Clients and 1 Server

Im very new to network programming. I have a UDP client/server that sends a message to a server in lower or uppercase. The server receives the message and relays it back with switches cases. I cant figure out how I would instead of relaying it back to the first client, sending it to client2. heres my code.
Server:
/*
Simple udp server
*/
#include<stdio.h> //printf
#include<string.h> //memset
#include<stdlib.h> //exit(0);
#include<arpa/inet.h>
#include<sys/socket.h>
#include<ctype.h>
#define BUFLEN 512 //Max length of buffer
#define PORT 8888 //The port on which to listen for incoming data
void die(char *s)
{
perror(s);
exit(1);
}
int main(void)
{
struct sockaddr_in si_me, si_other, si_other2;
int s, i, slen = sizeof(si_other) , recv_len;
char buf[BUFLEN];
//create a UDP socket
if ((s=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
{
die("socket");
}
// zero out the structure
memset((char *) &si_me, 0, sizeof(si_me));
si_me.sin_family = AF_INET;
si_me.sin_port = htons(PORT);
si_me.sin_addr.s_addr = htonl(INADDR_ANY);
//bind socket to port
if( bind(s , (struct sockaddr*)&si_me, sizeof(si_me) ) == -1)
{
die("bind");
}
//keep listening for data
while(1)
{
printf("Waiting for data...");
fflush(stdout);
//try to receive some data, this is a blocking call
if ((recv_len = recvfrom(s, buf, BUFLEN, 0, (struct sockaddr *) &si_other, &slen)) == -1) // read datagram from server socket
{
die("recvfrom()");
}
//print details of the client/peer and the data received
printf("Received packet from %s:%d\n", inet_ntoa(si_other.sin_addr), ntohs(si_other.sin_port)); printf("Data: %s\n" , buf);
//now reply to server socket/the client with the same data
if (sendto(s, buf, recv_len, 0, (struct sockaddr*) &si_other, slen) == -1)
{
die("sendto()");
}
}
close(s);
return 0;
}
The Client:
/*
Simple udp client
*/
#include<stdio.h> //printf
#include<string.h> //memset
#include<stdlib.h> //exit(0);
#include<arpa/inet.h>
#include<sys/socket.h>
#include<ctype.h>
#define SERVER "192.x.x.x"
#define BUFLEN 512 //Max length of buffer
#define PORT 8888 //The port on which to send data
void die(char *s)
{
perror(s);
exit(1);
}
int main(void)
{
struct sockaddr_in si_other;
int s, s2, i, slen=sizeof(si_other);
char buf[BUFLEN];
char message[BUFLEN];
if ( (s=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) // create a client socket
{
die("socket");
}
memset((char *) &si_other, 0, sizeof(si_other));
si_other.sin_family = AF_INET;
si_other.sin_port = htons(PORT);
if (inet_aton(SERVER , &si_other.sin_addr) == 0) // Create datagram with server IP and port.
{
fprintf(stderr, "inet_aton() failed\n");
exit(1);
}
while(1)
{
printf("Enter message : ");
gets(message);
int a;
char message2[BUFLEN];
for(a=0;a<=BUFLEN-1;a++)
{
if(message[a] >= 97 && message[a] <= 122)
message2[a] = toupper(message[a]);
else
message2[a] = tolower(message[a]);
}
if (sendto(s, message2, strlen(message2) , 0 , (struct sockaddr *) &si_other, slen)==-1)
{
die("sendto()");
}
//receive a reply and print it
//clear the buffer by filling null, it might have previously received data
memset(buf,'\0', BUFLEN);
//try to receive some data, this is a blocking call
if (recvfrom(s, buf, BUFLEN, 0, (struct sockaddr *) &si_other, &slen) == -1) // read datagram from client socket
{
die("recvfrom()");
}
puts(buf);
}
close(s);
return 0;
}
Since this has 21K views with no explicit answer, and it is basic understanding of coding for UDP.. I will give it some love.
As mentioned in the comments already: In your server code, you receive a message from the client using:
recvfrom(s, buf, BUFLEN, 0, (struct sockaddr *) &si_other, &slen))
The result of this function is that the message data will be written into buf and the ip address and port number of the socket that sent the message will be filled into si_other (which must be of type struct sockaddr_in).
So then, when you send a response using:
sendto(s, buf, recv_len, 0, (struct sockaddr*) &si_other, slen)
Since si_other, which you are passing as the destination address for sendto, contains the ip/port of the last message you got, the response will always go back to the sender of the last message you got. In many server applications this is a pretty common scenario: you get a request from somewhere, you send a response back to the same place.
If you want the message to go someplace else, other than the process that sent you the request, then you need to create a different struct sockaddr_in variable which contains the ip address and port of where you would like the message to go.
And in your client code, you already have the code that does that, eg (cleaned up a bit):
struct sockaddr_in si_client2;
memset((char *) &si_client2, 0, sizeof(si_client2));
si_client2.sin_family = AF_INET;
si_client2.sin_port = htons(CLIENT2_PORT);
if(inet_aton(CLIENT2_HOST, &si_client2.sin_addr) == 0)
perror("inet_aton");
So now, if you use si_client2 in your sendto(), the packet will go to that client.
Because it's UDP, delivery is not guaranteed. If there is a process listening for UDP at that ip address, on that port number, then (if no network error occurs) it will get the message. If not, nothing will happen.. your message vanishes into the void.
Keep in mind that if client 1 and client 2 are both running on the same machine, they will need to use different port numbers, because every destination (whether in a client or server role) must have a unique combination of IP and PORT.
Now, in real life applications, it is rare that a server will ever know the IP and PORT of its clients ahead of time.. usually clients will not use fixed port numbers but instead use "ephemeral ports".. port numbers which the operating system assigns at run-time. Whereas, the client will often be configured with the IP and port of the server.
So, in most cases, you would have some code in the server that keeps a list of client addresses.. perhaps a simple messaging service would keep a list of the last 100 clients it got messages from... But how this is actually done would be dictated by the needs of the application. For a simple exercise like this one, you can just hard code the addresses as I said...
The bottom line is that, to send a UDP packet to a specific destination, the sender must know the IP and PORT of that specific destination. And the only way to know that is either to have some configuration data, or for someone (such as the destination) to send a packet ahead of time letting you know of its existence. Just keep in mind that with a UDP socket you can get a message from anywhere, and you'll be given the ip/port along with the message. If you need to send a message, you need to know the ip/port of where you want to send it. It's your applications problem to figure out how it's going to get that information and where to store that information for later use.

Resources