I'm writing a simple network application and I need to craft a UDP packet and send it to a specific host.
int main(void){
// Message to be sent.
char message[] = "This is something";
int sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_UDP);
if(sockfd < 0){
perror("Error creating socket");
exit(1);
}
struct sockaddr_in this, other;
this.sin_family = AF_INET;
other.sin_family = AF_INET;
this.sin_port = htons(8080);
other.sin_port = htons(8000);
this.sin_addr.s_addr = INADDR_ANY;
other.sin_addr.s_addr = inet_addr("10.11.4.99");
if(bind(sockfd, (struct sockaddr *)&this, sizeof(this)) < 0){
printf("Bind failed\n");
exit(1);
}
char packet[64] = {0};
struct udphdr *udph = (struct udphdr *) packet;
strcpy(packet + sizeof(struct udphdr), message);
udph->uh_sport = htons(8080);
udph->uh_dport = htons(8000);
udph->uh_ulen = htons(sizeof(struct udphdr) + sizeof(message));
udph->uh_sum = 0;
if(sendto(sockfd, packet, udph->uh_ulen, 0, (struct sockaddr *) &other, sizeof(other)) < 0)
perror("Error");
else
printf("Packet sent successfully\n");
close(sockfd);
return 0;
}
Everything is working fine till the call to sendto(). The sendto() is giving "Bad address". can anyone point me where I'm going wrong? Is there any problem with binding a port to a raw socket?
The code transform the length of the messag (udph->uh_len) to network byte order (htons). This is not needed, as the parameter type of size_t. Only port number (in sockaddr structures) need the htons conversion.
udph->uh_ulen = sizeof(struct udphdr) + sizeof(message);
Current code produce large number (>8000) in uh_ulen, causing the send to fail.
I would like to build a client - server model where, for any number of clients connected to the server, the server should send a broadcast Message. Below is the code which I implemented, it does not throw any error, but I could not see any communication happening between the server and the client. Please let me know, where is the problem in the code.
I would like to see the message passed from the server on the clients system.
/************* UDP SERVER CODE *******************/
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char *argv[]){
int udpSocket, nBytes, buflen;
char buffer[1024];
char string[1024];
int portNum;
struct sockaddr_in serverAddr, clientAddr;
struct sockaddr_storage serverStorage;
socklen_t addr_size, client_addr_size;
int i;
/*Create UDP socket*/
udpSocket = socket(AF_INET, SOCK_DGRAM, 0);
portNum=atoi(argv[1]);
/*Configure settings in address struct*/
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(5000);
serverAddr.sin_addr.s_addr = inet_addr("192.168.1.117");
memset(serverAddr.sin_zero, '\0', sizeof serverAddr.sin_zero);
/*Bind socket with address struct*/
int bStatus=bind(udpSocket, (struct sockaddr *) &serverAddr, sizeof(serverAddr));
if (bStatus < 0) {
printf("error binding on server's port number\n");
exit(1);
}
/*Initialize size variable to be used later on*/
addr_size = sizeof serverStorage;
memset(&clientAddr, 0, sizeof(clientAddr));
clientAddr.sin_family = AF_INET;
clientAddr.sin_port = htons(portNum); // this is where client is bound
clientAddr.sin_addr.s_addr = inet_addr("192.168.1.114");
while(1){
sprintf(buffer,"Hello Client");
buflen=strlen(buffer);
int bytesSent = sendto(udpSocket,buffer,buflen,0,(struct sockaddr *)&clientAddr, sizeof(clientAddr));
if (bytesSent < 0) {
printf("Error sending/ communicating with client\n");
exit(1);
}
printf("%s\n",buffer);
/*
// ****************************************************
memset(buffer, 0, 1024);
buflen=65536;
recvfrom(udpSocket,buffer,buflen,0,(struct sockaddr *)&serverStorage, &addr_size);
printf("Received from server: %s\n",buffer);
*/
}
return 0;
}
Below is the client code :
/************* UDP CLIENT CODE *******************/
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
int main(int argc, char *argv[]){
int clientSocket, portNum, nBytes, buflen;
char buffer[1024];
char string[1024];
struct sockaddr_in serverAddr,clientAddr;
socklen_t addr_size;
/*Create UDP socket*/
clientSocket = socket(AF_INET, SOCK_DGRAM, 0);
portNum = atoi(argv[1]);
/*Configure settings in address struct*/
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(portNum);
serverAddr.sin_addr.s_addr = inet_addr("192.168.1.117");
// memset(serverAddr.sin_zero, '\0', sizeof serverAddr.sin_zero);
memset(&serverAddr,0,sizeof(serverAddr));
// binding
bind(clientSocket, (struct sockaddr *) &clientAddr, sizeof(clientAddr));
/*Initialize size variable to be used later on*/
addr_size = sizeof serverAddr;
while(1){
memset(buffer, 0, 1024);
buflen=65536;
recvfrom(clientSocket,buffer,buflen,0,(struct sockaddr *)&serverAddr, &addr_size);
//recvfrom(clientSocket,buffer,buflen,0,NULL,NULL);
printf("Received from server: %s\n",buffer);
/*
//********************************************************************
sprintf(buffer,"Hello Client");
buflen=strlen(buffer);
sendto(clientSocket,buffer,buflen,0,(struct sockaddr *)&serverAddr,addr_size);
printf("%s\n",buffer);
*/
}
return 0;
}
At a high level there are a few things that need to be addressed. Given the code in the post has a server that initiates communication with the client following line needs to be modified (and related code for these)
On the server side:
sendto(udpSocket,buffer,buflen,0,(struct sockaddr *)&serverStorage,addr_size);
Essentially what's happening here is that udpSocket is bound to serverAddr and we are trying to sendto serverStorage (2nd last argument). The trouble here is that the serverStorage is not bound to anything. Basically sendto has the source right but not the destination.
On the client side:
recvfrom(clientSocket,buffer,buflen,0,(struct sockaddr *)&serverAddr, &addr_size);
The clientSocket is not bound to anything so the system picks a random port where it will listen. In the recvfrom call, 2nd last argument captures the address details of the other side. Whereas in the code you have bound it to server's IP and port, it does not have any effect because it is filled in by the recvfrom call and returned.
To make things work here is what I'd suggest (you can add the details but have worked out the skeleton based on what you posted)
server_initiating_with_client.c
//...
int udpSocket, nBytes, buflen;
char buffer[1024];
int portNum;
struct sockaddr_in serverAddr, clientAddr;
struct sockaddr_storage serverStorage;
socklen_t addr_size, client_addr_size;
/*Create UDP socket*/
udpSocket = socket(AF_INET, SOCK_DGRAM, 0);
portNum=atoi(argv[1]);
/*Configure settings in address struct*/
memset(&serverAddr, 0, sizeof(serverAddr));
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(5000); // Making sure server has a unique port number
serverAddr.sin_addr.s_addr = htonl(INADDR_ANY);
/*Bind socket with address struct*/
int bStatus = bind(udpSocket, (struct sockaddr *) &serverAddr, sizeof(serverAddr));
if (bStatus < 0) {
printf("error binding on server's port number\n");
exit(1);
}
/*Initialize size variable to be used later on*/
addr_size = sizeof serverStorage;
/* Because server is initiating the communication here one needs to set the
* clientAddr and needs to know the port number of the client
*/
memset(&clientAddr, 0, sizeof(clientAddr));
clientAddr.sin_family = AF_INET;
clientAddr.sin_port = htons(portNum);
clientAddr.sin_addr.s_addr = htonl(INADDR_ANY);
while(1){
sprintf(buffer,"Hello Client");
buflen=strlen(buffer);
int bytesSent = sendto(udpSocket,buffer,buflen, 0,
(struct sockaddr *)&clientAddr,
sizeof(clientAddr));
if (bytesSent < 0) {
printf("Error sending/ communicating with client\n");
exit(1);
}
printf("Done sending %s\n", buffer);
sleep(1);
}
..
and on the client side something along these lines
//..
int clientSocket, portNum, nBytes, buflen;
char buffer[1024];
struct sockaddr_in serverAddr;
struct sockaddr_in clientAddr;
socklen_t addr_size;
/*Create UDP socket*/
clientSocket = socket(PF_INET, SOCK_DGRAM, 0);
portNum = atoi(argv[1]);
/*Configure settings in address struct*/
memset(&clientAddr, 0, sizeof(clientAddr));
clientAddr.sin_family = AF_INET;
clientAddr.sin_port = htons(portNum);
clientAddr.sin_addr.s_addr = htonl(INADDR_ANY);
memset(&serverAddr, 0, sizeof(serverAddr));
/*Bind on client side as well because you are specifically sending something over
* to the client. Usually the server will know where to talk back to the client
* but in your example because of the reversed semantics this will be needed
*/
bind(clientSocket, (struct sockaddr *) &clientAddr, sizeof(clientAddr));
/*Initialize size variable to be used later on*/
addr_size = sizeof serverAddr;
while(1){
memset(buffer, 0, 1024);
buflen=65536;
recvfrom(clientSocket,buffer,buflen,0,(struct sockaddr *)&serverAddr, &addr_size);
printf("Received from server: %s\n",buffer);
sleep(1);
}
return 0;
The code can be simplified if you reverse your comm from client to server, thereby, eliminating the need for a fixed port number on the client side.
just make a few changes in it. Assign a socket length predefined (socklen_t *) structure to typecast length
n = recvfrom(sockfd, (char *)buffer, MAXLINE,MSG_WAITALL, (struct sockaddr *) &servaddr, (socklen_t*)&len);
socklen_t* convert a length into socket length.
Make these changes at both client-side as well as a server-side
.
I'm writing an application that listens for UDP packets over a unix domain socket. Consider the following code block.
int sockfd;
struct sockaddr_un servaddr;
sockfd = socket(AF_LOCAL, SOCK_DGRAM, 0);
if(sockfd < 0)
{
perror("socket() failed");
}
unlink(port);
bzero(&servaddr, sizeof(servaddr));
servaddr.sun_family = AF_LOCAL;
strcpy(servaddr.sun_path, port);
if(bind(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0)
{
perror("bind() failed");
close(sockfd);
}
int n;
struct sockaddr_un cliaddr;
socklen_t len = sizeof(cliaddr);
discovery_msgs client_message;
bzero(&client_message, sizeof(client_message));
// Wait for a message to be received
n = recvfrom(sock_fd, &client_message, sizeof(client_message), 0,
(struct sockaddr *) &cliaddr, &len);
// At this point n = 560, client_message is filled with the expected data
//len = 0 and cliaddr has no information about the client that sent the data
Now the type of client_message isn't really important, I'm receiving a UDP packet and client_message contains all of the data I expect. The problem begins when I look at cliaddr and len after calling recvfrom. cliaddr is not modified by recvfrom like it normally is with normal network TCP/UDP and len is set to 0 after the call(which means recvfrom wrote no data to &cliaddr). I need the information in cliaddr to be populated with the unix domain path so I can send a response.
What am I doing wrong?
The solution is binding the socket on the client side when using Unix domain sockets. Otherwise the transient pathname created for sending the UDP packet immediately disappears after sendto(), which explains why the client's address information is not available on the server side.
See Stevens Network Programming page 419 or see this for an example client implementation that solves this issue: libpix.org/unp/unixdgcli01_8c_source.html
#include "unp.h"
int
main(int argc, char **argv)
{
int sockfd;
struct sockaddr_un cliaddr, servaddr;
sockfd = Socket(AF_LOCAL, SOCK_DGRAM, 0);
bzero(&cliaddr, sizeof(cliaddr)); /* bind an address for us */
cliaddr.sun_family = AF_LOCAL;
strcpy(cliaddr.sun_path, tmpnam(NULL));
Bind(sockfd, (SA *) &cliaddr, sizeof(cliaddr));
bzero(&servaddr, sizeof(servaddr)); /* fill in server's address */
servaddr.sun_family = AF_LOCAL;
strcpy(servaddr.sun_path, UNIXDG_PATH);
dg_cli(stdin, sockfd, (SA *) &servaddr, sizeof(servaddr));
exit(0);
}
Note: unp.h defines Bind() which is simply bind() with some error checking(commonly used throughout Stevens Network Programming). In the same manner, (SA *) is the equivalent to (struct sockaddr *).
I have opened an UDP socket to listen to incoming packet. I could see in the wireshark log the packets reaching the NIC. But the same is not available when reading via Socket. The 'netsatat ' command shows the port number is listened for the any incoming UDP messages. The socket reader keeps on waiting . I have checked using Java and C, in Linux(ubuntu) environment. I can see the Identification value for received IPV4 packet is 0. Is this value can play any role for a socket to read the data ?
My C code for reading the socket
int sock, n, nr;
socklen_t fromlen;
struct sockaddr_in server;
struct sockaddr_in from;
sock = socket(AF_INET, SOCK_DGRAM, 0);
if (sock < 0)
printf("Can not create socket in server\n");
memset(&server, 0, sizeof(struct sockaddr_in));
server.sin_family = AF_INET;
server.sin_port = htons(5555);
server.sin_addr.s_addr = INADDR_ANY;
if(bind(sock, (struct sockaddr *)&server, sizeof(server)) < 0)
fromlen = sizeof(struct sockaddr_in);
while(1) {
printf("Waiting to receive\n");
n = recvfrom(sock, &nr, sizeof(nr), 0, (struct sockaddr *) &from, &fromlen);
printf("I have received");
}
Please find the wireshark trace http://imgur.com/Au9BeS1
This is a problem:
if(bind(sock, (struct sockaddr *)&server, sizeof(server)) < 0)
fromlen = sizeof(struct sockaddr_in);
This will only set fromlen is the bind call fails. And since fromlen is not properly initialized, it will contain a seemingly random value that is not valid for recvfrom.
I have a socket server running on multiple machines. It works like a charm besides on one machine.
The server binds correctly but returns an error (EFAULT) when the client attempts to connect.
Perhaps someone has an idea what the source of the problem might be. Thanks a lot in advance!
Some information about the machine:
Linux version 2.6.18.3
gcc version 3.3.5 (Debian 1:3.3.5-13)
The socket server source is pretty straight forward.
...
...
struct sockaddr_in server_addr;
struct sockaddr* client;
socklen_t alen;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == -1) {
...
}
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = INADDR_ANY;
server_addr.sin_port = htons(port);
if(bind(sockfd, (struct sockaddr *) &server_addr, sizeof(server_addr)) < 0){
...
}
if(listen(sockfd,BACKLOG) == -1){
...
}
alen = sizeof(client);
new_fd = accept(sockfd, client, &alen);
if (new_fd == -1) {
/*
* this part of the code is executed
* errno is set to 14
*/
}
Thank you for pointing me in the right direction.
Use this:
struct sockaddr_in client;
...
alen = sizeof(client);
new_fd = accept(sockfd, (struct sockaddr *) &client, &alen);
accept expects a pointer to an existing buffer which it'll fill in. You have two errors, you set alen to the size of a pointer, and you pass an uninitialized pointer to accept.
From the accept(2) man page:
EFAULT The addr argument is not in a writable part of the user address
space.
Check to make sure that you've allocated client appropriately.