UDP Sockets in C - Sendto() Send failed : invalid arguments - c

I am trying to implement UDP sockets in C in a very simple/basic fashion. My programs are meant to send/receive files between terminals with one program running on each. I am having a problem with the sendto() function in my client code. Here is my code:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<arpa/inet.h>
#include<sys/socket.h>
#include <errno.h>
#define BUFFER_SIZE 512
int main(int argc, char *argv[])
{
struct sockaddr_in client;
int sockfd, bytes, errno, slen = sizeof(client);
char buffer[BUFFER_SIZE];
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if(sockfd == -1)
{
perror("Socket creation failed.");
return 0;
}
client.sin_addr.s_addr = INADDR_ANY;
client.sin_family = AF_INET;
client.sin_port = htons( 0 );
if( bind(sockfd, (struct sockaddr *)&client, sizeof(client)) == -1)
{
perror("Bind call failed.");
return 0;
}
while(1)
{
printf("Enter message : ");
fgets(buffer, BUFFER_SIZE, stdin);
printf("Message: %s\n", buffer);
bytes = sendto(sockfd, buffer, strlen(buffer), 0, (struct sockaddr *)&client, sizeof(client));
printf("Bytes: %d\n", bytes);
if(bytes == -1)
{
printf("Error number: %d", errno);
perror("Send failed.");
return 0;
}
memset(buffer,'\0', BUFFER_SIZE);
if( recvfrom(sockfd, buffer, BUFFER_SIZE, 0, (struct sockaddr *)&client, &slen) == -1)
{
perror("Recieve failed.");
return 0;
}
puts(buffer);
}
close(sockfd);
return 0;
}
No matter what I enter into the buffer, I always get error number 22 from sendto() for invalid arguments. I have tried every solution or tweak I have come across but nothing seems to work.

Just add this piece of code after bind()
getsockname(sockfd, (struct sockaddr *)&client, &slen);
man page
DESCRIPTION
The getsockname() function returns the current address for the specified
socket.
The address_len parameter should be initialized to indicate the amount of
space pointed to by address. On return it contains the actual size of
the address returned (in bytes).
The address is truncated if the buffer provided is too small.
RETURN VALUES
The getsockname() function returns the value 0 if successful; otherwise
the value -1 is returned and the global variable errno is set to indicate
the error.

Related

Address family not supported by protocol UDP C Error sending

I'm trying to implement communication by UDP protocol, and I'm getting an error: "Error sending: Address family not supported by protocol". I've checked in Google for this problem but couldn't managed to find answer.
Please be patient, I'm only starting my adventure with coding in C.
Here is a C code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#define BUFLEN 512
// define function that deals with errors
void error(const char *msg)
{
perror(msg); // print error msg
exit(1); // exit the main() function
}
int main(int argc, char *argv[])
{
struct sockaddr_in serv1_addr, serv2_addr, cli1_addr, cli2_addr; //definicja struktur adresów servera i clienta
struct hostent *server; //defines host addres struct
int cl1_sockfd, se1_sockfd, se2_sockfd, i, c1len = sizeof(cli1_addr), c2len = sizeof(cli2_addr), recv_len, portno1,portno2; // creates inits
int cli1_len = sizeof(cli1_addr);
int cli2_len = sizeof(cli2_addr);
char buf[BUFLEN];
if (argc < 4) {
fprintf(stderr,"ERROR, no port provided\n"); // deal with wrong port
exit(1);
}
//tworzenie soceketu servera
if ((se1_sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1){
error("socket1"); //if socket() return -1 -- error
}
if ((se2_sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1){
error("socket2"); //if socket() return -1 -- error
}
//zero out the structure
memset( &serv1_addr, 0, sizeof(serv1_addr)); //put zero into structure
memset( &serv2_addr, 0, sizeof(serv2_addr)); //put zero into structure
portno1 = atoi(argv[2]); // get port number
portno2 = atoi(argv[3]);
serv1_addr.sin_family = AF_INET; // specify address family (IPv4)
serv1_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
serv1_addr.sin_port = htons(portno1); // set port number
serv2_addr.sin_family = AF_INET; // specify address family (IPv4)
serv2_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
serv2_addr.sin_port = htons(portno2); // set port number
if(connect(se1_sockfd,(struct sockaddr *) &serv1_addr, sizeof(serv1_addr)) < 0)
error ("ERROR connecting1"); //if connection failed
if(connect(se2_sockfd,(struct sockaddr *) &serv2_addr, sizeof(serv2_addr)) < 0)
error ("ERROR connecting2"); //if connection failed
while(1) //inf loop
{
printf("Please enter the message: "); //write the msg to socket
bzero(buf, 512); //fill buffer with zeros
fgets(buf, 512, stdin); //read into buffer
if( sendto( se1_sockfd, buf, BUFLEN, 0, (struct sockaddr*) &cli1_addr, cli1_len) < 0)
error ("Error sending1");
if( sendto( se2_sockfd, buf, BUFLEN, 0, (struct sockaddr*) &cli2_addr, cli2_len) < 0)
error ("Error sending2");
if (recvfrom(se1_sockfd, buf, BUFLEN, 0, (struct sockaddr *) &cli1_addr, &cli1_len) == -1){
error("recivfrom()1"); //if reciving failed -- error
}
printf("Data: %s\n", buf);
if (recvfrom(se2_sockfd, buf, BUFLEN, 0, (struct sockaddr *) &cli2_addr, &cli2_len) == -1){
error("recivfrom()2"); //if reciving failed -- error
}
printf("Data: %s\n", buf);
}
close(se1_sockfd);
close(se2_sockfd);
return 0;
}
Thanks for your help. ;)
Your issue is likely because of uninitialized destination address. sendto() takes destination address as the one before the last argument. But you are trying to provide not-initialized address (like for recvfrom())
if( sendto( se1_sockfd, buf, BUFLEN, 0, (struct sockaddr*) &cli1_addr, cli1_len) < 0)
error ("Error sending1");
^^^
Try serv1_addr instead ?
Also need to provide appropriate size.
One more thing. As long as you use sendto() - no need to perform connect(). UDP is connectionless and connect() only establishes default destination address for those who is going to use send() on such socket. But this is not your case because you provide destination address each time you call sendto(). Even more - you may use different addresses each time.
P.S. Reference: sendto()

UDP socket: invalid argument error in sendto

I'm trying to write a simple UDP socket client-server program. The client machine is supposed to send a string to the server, that will answer with an ACK message.
Here's the implementation of the client side:
int main() {
message_send('L');
return EXIT_SUCCESS;
}
int message_send(char code) {
int sockfd;
ssize_t n;
char recvline[MAXLINE + 1];
struct sockaddr_in servaddr;
// Create an UDP socket
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0) {
perror("socket");
return -1;
}
// Setup the socket
memset((void *) &servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = (in_port_t) htonl(SERV_PORT);
if (inet_pton(AF_INET, SERVIP, &servaddr.sin_addr) <= 0) {
fprintf(stderr, "Error in inet_pton for %s\n", SERVIP);
exit(1);
}
// Send a test string
char *test = malloc(MAXLINE);
snprintf(test, MAXLINE, "SENDING:%c", code);
if (sendto(sockfd, &test, sizeof(test), 0, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0) {
perror("sendto");
return -1;
}
// Get an answer from the server
n = recvfrom(sockfd, recvline, MAXLINE, 0, NULL, NULL);
if (n < 0) {
perror("recvfrom");
exit(1);
} else if (n > 0) {
recvline[n] = 0; // Add ending character
if (fputs(recvline, stdout) == EOF) { // Print the received message in stdout
perror("fputs");
return -1;
}
}
return 0;
}
If I run this (whether the server machine is running or not) I get the following error:
sendto: Invalid argument
Why am I getting this error?
The most likely cause of the problem is the line
servaddr.sin_port = (in_port_t) htonl(SERV_PORT);
I'm guessing that gives you a bad port number (i.e. it will give you port 0 on a little endian machine). Port numbers are 16-bit, so you should be using htons.
Also, passing &test and sizeof(test) to sendto will send the pointer value over the network. To send the string, you need to use test and strlen(test)+1.

maximum data that can be sent through a port-socket

i have implemented a program which takes input from client, performs operation on server and writes the data to the client. ls command is what i have chosen for example.
Now my doubt is,
1) what if the input is very huge in bytes??
2) what is the maximum data that can be sent through a socket port??
client.c
int main()
{
FILE *fp;
int servfd, clifd;
struct sockaddr_in servaddr;
struct sockaddr_in cliaddr;
int cliaddr_len;
char str[4096], clientip[16];
int n;
servfd = socket(AF_INET, SOCK_STREAM, 0);
if(servfd < 0)
{
perror("socket");
exit(5);
}
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(SERVPORT);
servaddr.sin_addr.s_addr = inet_addr(SERVIP);
if(bind(servfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0)
{
perror("bind");
exit(0);
}
listen(servfd, 5);
printf("Server is waiting for client connection.....\n");
while(1)
{
cliaddr_len=sizeof(cliaddr);
clifd = accept(servfd, (struct sockaddr *)&cliaddr, &cliaddr_len);
strcpy(clientip, inet_ntoa(cliaddr.sin_addr));
printf("Client connected: %s\n", clientip);
if(fork() == 0)
{
close(servfd);
while(1)
{
n = read(clifd, str, sizeof(str));
str[n] = 0;
if(strcmp(str, "end") == 0)
{
printf("\nclient(%s) is ending session and server is waiting for new connections\n\n", clientip);
break;
}
else if (strcmp(str, "ls") == 0) {
system("ls >> temp.txt");
fp = fopen("temp.txt", "r");
fread(str, 1, 500, fp);
remove("temp.txt");
}
else
printf("Received from client(%s): %s\n", clientip, str);
write(clifd, str, strlen(str));
}
close(clifd);
exit(0);
}
else
{
close(clifd);
}
}
}
server.c
int main()
{
int sockfd;
struct sockaddr_in servaddr;
char str[500];
int n;
sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(SERVPORT);
servaddr.sin_addr.s_addr = inet_addr(SERVIP);
if(connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0)
{
printf("Could not connect to server: %s\n", strerror(errno));
exit(1);
}
while(1)
{
printf("Enter message: ");
scanf(" %[^\n]", str);
write(sockfd, str, strlen(str));
if(strcmp(str, "end") == 0)
break;
n = read(sockfd, str, sizeof(str));
str[n] = 0;
printf("Read from server: %s\n", str);
}
close(sockfd);
}
As for your question no 1. the huge data is broken in many packets & then sent packet by packet its done by OS internally. & the one packet size depends on your system OS(you can change it.It is called MTU maximum transfer unit).
& for your question no 2. the data send by a socket port may be infinite coz as long as u wish to send data it will send. there is no limit.!!!
Q: What if the input is very huge in bytes?? What is the maximum data that can be sent through a socket port??
A: There is no limit on the size of a TCP/IP stream. In theory, you could send and receive an infinite number of bytes.
... HOWEVER ...
1) The receiver must never assume is will ever get all the bytes at once, in a single read. You must always read socket data in a loop, reading as much at a time as you wish, and appending it to the data you've already read.
2) You can send a "large" amount of data at once, but the OS will buffer it behind your back.
3) Even then, there's an OS limit. For example, here the maximum send buffer size is 1 048 576 bytes.:
http://publib.boulder.ibm.com/infocenter/tpfhelp/current/index.jsp?topic=%2Fcom.ibm.ztpf-ztpfdf.doc_put.cur%2Fgtpc2%2Fcpp_send.html
If you need to send more, you must send() in a loop.
PS:
As Anish recommended, definitely check out Beej's Guide to Network programming:
http://beej.us/guide/bgnet/output/html/multipage/

UDP Sockets in C: client1 to server to client2

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 switched cases. I can't figure out how I would instead of having the server relay it back to the first client, instead sending it to a client2. If my client2 sends a message the server receives and sends it back to client2 and same thing with client1. I want what client1 says to be sent to the server and then the server send that to client2. I've tried everything i can think of but cant figure out.
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;
}
It seems instead of a UDP server, you want to have a forwarder of packets like from client->server->client2, so you need to tell your server the ipaddress/port of client2, for this kindly configure client2 ip/port in server either using commandline arguments or read any input file, then before the sendto statement in server code, fill the si_other structure with client2 information as teken from command line or input file.
After you read() or recvfrom() your message, you process your data and then sendto() twice: one to the address returned by recvfrom() (the original sender) and other to the other client's address (which must be provided or detected somehow by your server).
Something along this (proper error checking not being performed):
char data[100];
struct sockaddr_in address;
socklen_t length = sizeof address;
/* Receive data from any client. */
ssize_t result = recvfrom(server, data, sizeof data, 0, &address, &length);
/* Process the data (change cases). */
process_data(data, result);
/* Send back to the first client. */
sendto(server, data, result, 0, &address, sizeof address);
/* Check who's the sender and relay to the other. */
if (address.sin_addr.s_addr == CLIENT1_ADDRESS)
address.sin_addr.s_addr = CLIENT2_ADDRESS;
else
address.sin_addr.s_addr = CLIENT1_ADDRESS;
/* Send to the other client. */
sendto(server, data, result, 0, &address, sizeof address);
In this example, the addresses are statically defined.

Socket, accept() function, Invalid argument

I am getting an error "Invalid argument" when i call the accept() function on the server side of a client-server application. I don't get what is wrong and if you see what is wrong let me know please. Thanks.
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
int main(int argc, char* argv[])
{
int sockfd, newsockfd, portno, len;
struct sockaddr_in server, client;
if(argc < 2){
perror("Add more arguments");
}
sockfd = socket(AF_UNIX,SOCK_STREAM,0);
if(sockfd < 0){
perror("Error at socket()");
}
printf("Socketfd: %d\n",sockfd);
bzero((char *)&server, sizeof(server));
portno = atoi(argv[1]);
server.sin_family = AF_UNIX;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons(portno);
if(bind (sockfd, (struct sockaddr *)&server, sizeof(server)) <0){
perror("Error at bind ()-server");
}
listen(sockfd,5);
int readval;
char buffer[256];
for(;;){
len = sizeof(client);
newsockfd = accept (sockfd, (struct sockaddr *)&server,&len);
if (newsockfd == -1){
perror("Erroare at accept()");
}
else do{
readval = (sockfd,buffer,sizeof(buffer));
if (readval < 0 ){
perror("Error at reading()");
}
else if (readval == 0){
printf("End conection");
}
else{
printf("Mesage is: %s\n", buffer);
}
}while (readval > 0);
close(newsockfd);
}
return 0;
}
You have to use sockaddr_un instead of sockaddr_in for Unix domain sockets OR substitute AF_UNIX with AF_INET.
Plus, check the return of listen.
Plus change this line
readval = (sockfd,buffer,sizeof(buffer));
with
readval = read(newsockfd,buffer,sizeof(buffer));
because data is going to be sent through the newly created socket and not on the listening one
Plus, as mentioned by #trojanfoe, subst the server with the client structure into the accept() call
This line:
newsockfd = accept (sockfd, (struct sockaddr *)&server, &len);
Should be:
newsockfd = accept (sockfd, (struct sockaddr *)&client, &len);
From the manpage:
The argument addr is a pointer to a sockaddr structure. This structure
is filled in with the address of the peer socket, as known to the
communications layer. The exact format of the address returned addr is
determined by the socket's address family (see socket(2) and the
respective protocol man pages). When addr is NULL, nothing is filled
in; in this case, addrlen is not used, and should also be NULL.
Also check the return value from listen().
I ran into a similar issue before and it was due to not having the read function in a loop. Here is an example I did before.
while (1) {
new_sockfd = accept(sockfd, (struct sockaddr *) &client_addr,
&sin_size);
if (new_sockfd == -1)
perror("accepting connection");
printf("server: got connection from %s port %d\n",
inet_ntoa(client_addr.sin_addr),
ntohs(client_addr.sin_port));
recv_length = recv(new_sockfd, &buffer, DATA, 0);
while (recv_length > 0) {
printf("RECV: %d bytes\n", recv_length);
dump(buffer, recv_length);
recv_length = recv(new_sockfd, &buffer, DATA, 0);
}
close(new_sockfd);
}

Resources