I'm trying to open a socket in UDP and subsequently send a message using it. This is the code that opens the socket.
sockfd = startServer(char* ip_addr, int port, struct sockaddr_in server){
int sockfd, len;
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if(sockfd < 0){
perror("Failed to open socket: ");
exit(-1);
}
len = sizeof(server);
bzero(&server, len);
server.sin_family= AF_INET;
inet_aton(ip_addr, &server.sin_addr.s_addr);
server.sin_port= htons(port);
if((bind(sockfd, (struct sockaddr*)&server, len)) < 0){
perror("Bind failed: ");
exit(-1);
}
return sockfd;
}
Now to send a message on this socket. I use this function.
void sendMessage(char* msg, int sockfd, struct sockaddr_in client, int len){
int sbytes = 0;
sbytes = sendto(sockfd, msg, strlen(msg), 0, (struct sockaddr*)&client, len);
if(sbytes < 0){
perror("Error sending message: ");
}
printf("Routing vector sent to %s\n", inet_ntoa(client.sin_addr));
}
I keep getting the following error.
error: incompatible pointer types passing 'in_addr_t *' (aka 'unsigned int *') to parameter of type 'struct in_addr *' [-Wincompatible-pointer-types]
inet_aton(ip_addr, &server.sin_addr.s_addr);
^~~~~~~~~~~~~~~~~~~~~~~
Any help appreciated.
The second parameter to inet_aton expects a struct in_addr *. You're passing in &server.sin_addr.s_addr, which is an in_addr_t *.
What you want is this:
inet_aton(ip_addr, &server.sin_addr);
Since server.sin_addr is a struct in_addr.
Related
I have two programs: client and server. They're trying to find themselves in local network using broadcast.
Client sends simple packet on broadcast with SERVER_PORT (known before) and server prints info about connection, but when i tried this solution I found some strange behavaiour, when I uncomment last two lines of server.c server prints (one custom struct)
Connection from: 0.0.0.0 on port: 0
after commenting those lines everything works properly, am I missing something?
server.c
int broadcast_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
struct sockaddr_in broadcast_addr;
broadcast_addr.sin_addr.s_addr = INADDR_ANY;
broadcast_addr.sin_port = htons(SERVER_PORT);
broadcast_addr.sin_family = AF_INET;
if (bind(broadcast_socket, (struct sockaddr *)&broadcast_addr,
sizeof(broadcast_addr))) {
perror("bind");
}
struct sockaddr_in recv_addr;
char buf[MAX_PACKET_SIZE];
socklen_t len;
if (recvfrom(broadcast_socket, buf, MAX_PACKET_SIZE, 0,
(struct sockaddr *)&recv_addr, &len) < 0) {
perror("recvfrom");
}
printf("Connection from: %s on port: %d\nMessage: %s\n",
inet_ntoa(recv_addr.sin_addr), ntohs(recv_addr.sin_port), buf);
/* struct network_packet packet; */
/* struct sockaddr_in my_addr; */
client.c
int find_server(struct sockaddr_in *out) {
struct sockaddr_in broadcast;
struct network_packet packet;
int yes = 1;
socklen_t len;
broadcast.sin_addr.s_addr = INADDR_ANY;
broadcast.sin_port = htons(CLIENT_PORT);
broadcast.sin_family = AF_INET;
int socket_fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (bind(socket_fd, (struct sockaddr *)&broadcast, sizeof(broadcast))) {
perror("bind");
}
if (get_broadcast_addr(&broadcast.sin_addr)) {
return -1;
}
printf("Target address: %s\n", inet_ntoa(broadcast.sin_addr));
broadcast.sin_port = htons(SERVER_PORT);
broadcast.sin_family = AF_INET;
setsockopt(socket_fd, SOL_SOCKET, SO_BROADCAST, &yes, sizeof(yes));
char buf[10] = "test";
sendto(socket_fd, buf, strlen(buf), 0, (struct sockaddr *)&broadcast,
sizeof(broadcast));
if (recvfrom(socket_fd, &packet, sizeof(packet), 0,
(struct sockaddr *)&broadcast, &len) < 0) {
perror("recvfrom");
}
struct sockaddr_in *sa = (struct sockaddr_in *)packet.data;
memcpy(out, sa, packet.header.packet_length);
return 0;
}
struct network_packet_header {
enum network_packet_type type;
int packet_length;
};
struct network_packet {
struct network_packet_header header;
unsigned char data[MAX_DATA_LENGTH];
};
You have to initialize the variable you pass as recvfrom's addrlen to the size of the address struct.
I'm writing a server-client application using UDP protocol. When I run the recvfrom I get the following error and I really can't understand why:
recvfrom: Invalid argument
Here's what I assumed is the code relative to this error:
#define CLIE_PORT 5499
#define MAXMSGSIZE (1024 * 1024) // Max message size is 1MB
#define CLIE_PORT 5499
#define PACKETSZ 7
I'm running rcv_string in this way:
char *result = malloc(MAXMSGSIZE);
struct sockaddr_in sndaddr;
rcv_string((uint16_t) CLIE_PORT, &result, &sndaddr);
Here's the implementation of rcv_string (inside there's the call to recvfrom).
int rcv_string(uint16_t port, char **return_string, struct sockaddr_in *sndaddr) {
// [...]
memset((char *) sndaddr, 0, sizeof(*sndaddr));
(*sndaddr).sin_family = AF_INET;
(*sndaddr).sin_port = htons(port);
int reuse = 1;
if (setsockopt(sockfd_in, SOL_SOCKET, SO_REUSEADDR, (const char *) &reuse, sizeof(reuse)) < 0) {
perror("setsockopt");
return -1;
}
if (bind(sockfd_in, (struct sockaddr *) sndaddr, sizeof(*sndaddr)) < 0) {
perror("bind");
return -1;
}
socklen_t len;
if ((recvfrom(sockfd_in, buff, PACKETSZ + 1, 0, (struct sockaddr *) sndaddr, &len)) < 0) {
perror("recvfrom");
return -1;
}
// [...]
}
What could be the problem? (If you think I should upload more code, tell me!)
I think it should be socklen_t len=sizeof(*sndaddr);.
I'm currently setting up a UDP socket for a school assignment but I can't figure out how to properly send sockaddr as a parameter into a function. The input arguments for SendData is defined the same way they are in the sendto function.
void SendData(int fileDescriptor, const struct sockaddr_in *destAddrUdp, unsigned char buffer[MAXMSG])
{
/* crc */
int strlength = strlen(buffer);
unsigned char SCRC = CRC(buffer, strlength-1);
buffer[strlength-1] = SCRC;
buffer[strlength] = '\0';
/* send */
if (sendto(fileDescriptor, buffer, strlen(buffer), 0, (struct sockaddr*) &destAddrUdp,sizeof(destAddrUdp)) < 0) {
fprintf(stderr, "Could not send data\n");
}
} `
When the below code is called from main it works however when it's called from SendData the return value from sendto is -1.
if (sendto(fileDescriptor, buffer, strlen(buffer), 0, (struct sockaddr*) &destAddrUdp,sizeof(destAddrUdp)) < 0) {
fprintf(stderr, "Could not send data\n");
}
If the program is compiled I get warning: passing argument 5 of ‘recvfrom’ from incompatible pointer type. on the sendto functioncall in SendData.
The function call for SendData in my main program is: SendData(sockfd, (struct sockaddr *) &destAddrUdp, buffer);
The main program in case it is relevant:
unsigned char SCRC;
unsigned char strlength;
unsigned char buffer[MAXMSG-5];
unsigned char header[MAXMSG];
struct rtp_struct *sendstruct;
/* option 2 */
struct sockaddr_in destAddrUdp;
int sockfd;
char dstHost[15];
printf("input host IP:\n>");
fgets(dstHost, 15, stdin);
/* Create socket */
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
fprintf(stderr, "Can't create UDP socket\n");
/* set configurations */
memset (&destAddrUdp, 0, sizeof(destAddrUdp)); //set zero
destAddrUdp.sin_family = AF_INET; //internet use
destAddrUdp.sin_addr.s_addr = inet_addr(dstHost); //set so anyone can connect
destAddrUdp.sin_port = htons(dstUdpPort); //set the port to use
/* Generate CRC table */
GenerateCRCTable();
/* get string and send */
while(1) {
printf("\n>");
fgets(buffer, MAXMSG, stdin);
if(strncmp(buffer,"quit\n",MAXMSG) != 0){ //if read string == quit, see else
strlength = strlen(buffer);
SCRC = CRC(buffer, strlength-1);
buffer[strlength-1] = SCRC;
buffer[strlength] = '\0';
SendData(sockfd, (struct sockaddr *) &destAddrUdp, buffer);
/*if (sendto(sockfd, buffer, strlength, 0, (struct sockaddr *) &destAddrUdp,sizeof(destAddrUdp)) < 0){
fprintf(stderr, "Could not send data\n");}*/
}
else {
close(sockfd);
exit(EXIT_SUCCESS);
}
}
}
In your SendData function, the parameter destAddrUdp has type const struct sockaddr_in *. When you then make this call:
sendto(fileDescriptor, buffer, strlen(buffer), 0,
(struct sockaddr*) &destAddrUdp, sizeof(destAddrUdp)
The expression &destAddrUdp has type const struct sockaddr_in **, so the pointer type is incompatible. Also, sizeof(destAddrUdp) is returning the size of a pointer, not the size of the struct.
You failed to account for the differing types of destAddrUdp in SendData and main. The correct call to sendto would be:
sendto(fileDescriptor, buffer, strlen(buffer), 0,
(struct sockaddr*) destAddrUdp, sizeof(*destAddrUdp)
The problem is the sizeof(destAddrUdp) and the (struct sockaddr*) &destAddrUdp.
In your main, destAddrUdp is an struct sockaddr_in, in your function however, its a sockaddr_in* so you can't use them equally. First, sizeof(destAddrUdp) in your function will give you the size of a pointer, second, &destAddrUdp in your function will give you a destAddrUdp**. Thats not what you want.
Try sendto(fileDescriptor, buffer, strlen(buffer), 0, (struct sockaddr*) destAddrUdp,sizeof(*destAddrUdp))
I've declared a pointer to the following struct in my main function
struct sockaddr_in* server;
I'm using this struct to a function that returns a socket descriptor bound to this struct.
int openSocket(char* ip_addr, int port, struct sockaddr_in* server){
int sockfd, len;
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if(sockfd < 0){
perror("Failed to open socket: ");
exit(-1);
}
len = sizeof(server);
bzero(&server, len);
server->sin_family= AF_INET;
inet_aton(ip_addr, &server->sin_addr);
server->sin_port= htons(port);
if((bind(sockfd, (struct sockaddr*)&server, len)) < 0){
perror("Bind failed: ");
exit(-1);
}
return sockfd;
}
However when I try to read the individual fields in the struct that was passed into the function, I get a seg fault. That is when I run the following code in my main
sockfd = openSocket(vector->ip_addr, vector->port, server);
printf("%s %d\n", inet_ntoa(server->sin_addr), htons(server->sin_port) );
The values being passed into the openSocket function are correct.
I get a segmentation fault. Any help appreciated.
After I looked through your codes again, I found there are three mistakes.
In main(), you just declared one pointer to struct sockaddr_in, but you didn't assign it, you can define struct sockaddr_in server and pass &server to openSocket().
In openSocket, "server" is declared to pointer, but your statements len = sizeof(server); bzero(&server, len); are not correct, this is where your segmentation violation occurs.
In openSocket(), bind(sockfd, (struct sockaddr*)&server, len) is not correct, you don't need to use &server, just use server.
So you should change your code as below:
len = sizeof(server); ----> len = sizeof(struct sockaddr_in)
bzero(&server, len); ----> bzero(server, len);
if((bind(sockfd, (struct sockaddr*)&server, len)) < 0){ ----->
if((bind(sockfd, (struct sockaddr*)server, len)) < 0){
struct sockaddr_in* server;
sockfd = openSocket(vector->ip_addr, vector->port, server);
printf("%s %d\n", inet_ntoa(server->sin_addr), htons(server->sin_port) );
---->
struct sockaddr_in server;
sockfd = openSocket(vector->ip_addr, vector->port, &server);
printf("%s %d\n", inet_ntoa(server.sin_addr), htons(server.sin_port) );
You just declared "server" as a pointer to struct sockaddr_in, but you didn't assign it. You can do it like below:
struct sockaddr_in server;
sockfd = openSocket(vector->ip_addr, vector->port, &server);
printf("%s %d\n", inet_ntoa(server.sin_addr), htons(server.sin_port) );
bind(sockfd, (struct sockaddr*)&server, len)
The problem is here. server is already a pointer. You should not take its address.
bind(sockfd, (struct sockaddr*)server, len)
And, as pointed out by #nos, you need to initialize it somewhere. There's no reason for the static variable to be a pointer. It can just be a struct sockaddr_in.
I had earlier posted a question, regarding same, but over here i want guidance for my code. Using the tips from people I have tried to create for sending a packet. My max packet structure alongwith header and payload is of 16 bytes.Kindly if possible glance through the sending and receiving code and suggest where i am going wrong. Basically my client keeps sending data to server,it just doesn't end and server doesn't show results.
Client:
int main(int argc, char *argv[])
{
int sockfd, portno, n;
struct sockaddr_in serv_addr;
struct hostent *server;
struct packet
{
long int srcID;
long int destID;
long int pver;
long int profiles;
char length;
long int data;
};
if (argc < 3) {
fprintf(stderr,"usage: %s hostname port\n", argv[0]);
exit(0);
}
portno = atoi(argv[2]); //Convert ASCII to integer
sockfd = socket(AF_INET, SOCK_STREAM, 0); // socket file descriptor
if (sockfd < 0)
error("ERROR DETECTED !!! Problem in opening socket\n");
server = gethostbyname(argv[1]);
if (server == NULL) {
fprintf(stderr,"ERROR DETECTED !!!, no such server found \n");
exit(0);
}
bzero((char *) &serv_addr, sizeof(serv_addr)); //clear the memory for server address
serv_addr.sin_family = AF_INET;
bcopy((char *)server->h_addr,
(char *)&serv_addr.sin_addr.s_addr,
server->h_length);
serv_addr.sin_port = htons(portno);
printf("Client 1 trying to connect with server host %s on port %d\n", argv[1], portno);
if (connect(sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr)) < 0)
error("ERROR in connection");
printf("SUCCESS !!! Connection established \n");
char buffer[128];
struct packet *pkt = (struct packet *) buffer;
char *payload = buffer + sizeof(struct packet);
long int packet_size;
printf("Started Creating packet\n");
pkt->srcID = 0x01;
pkt->destID = 0x02;
pkt->pver = 0x01;
pkt->profiles = 0x01;
pkt->length = 128;
pkt->data = 1; 2; 3; 4; 5; 6; 7; 8;
if (send(sockfd,pkt,sizeof(packet_size),0) <0)
printf ("error\n");
else
printf ("packet send done");
return 0;
}
Server:
int main(int argc, char *argv[])
{
int sockfd, newsockfd, portno, clilen;
struct sockaddr_in serv_addr, cli_addr;
int n;
char wish;
long int SrcID;
long int DestID;
long int Pver;
long int Profiles;
long int Data;
char Length;
char bytes_to_receive;
char received_bytes;
struct packet
{
long int srcID;
long int destID;
long int pver;
long int profiles;
char length;
long int data;
};
if (argc < 2) {
fprintf(stderr,"usage: %s port_number1",argv[0]);
exit(1);
}
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR DETECTED !!! Problem in opening socket");
bzero((char *) &serv_addr, sizeof(serv_addr));
portno = atoi(argv[1]);
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(portno);
if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
error("ERROR DETECTED !!! There was a problem in binding");
listen(sockfd, 10);
clilen = sizeof(cli_addr);
printf("Server listening on port number %d...\n", serv_addr.sin_port);
newsockfd = accept(sockfd,(struct sockaddr *) &cli_addr, &clilen);
if (newsockfd < 0)
error("ERROR DETECTED !!! the connection request was not accepted");
char buffer[128];
struct packet *pkt = (struct packet *) buffer;
char *payload = buffer + sizeof(struct packet);
long int packet_size;
bytes_to_receive = sizeof(pkt);
received_bytes = 0;
if (recv(newsockfd, pkt, sizeof(pkt), 0) < 0)
error("ERROR DETECTED !!! There was a problem in reading the data");
else
{
do {
received_bytes += (buffer + received_bytes, bytes_to_receive - received_bytes);
} while (received_bytes != bytes_to_receive);
SrcID = pkt->srcID;
DestID = pkt->destID;
Pver = pkt->pver ;
Profiles = pkt->profiles;
Length = pkt->length;
Data = pkt->data;
printf("Data Received from Client_1 are :\n");
printf("Source ID: %l\n", SrcID);
printf("Destination ID: %l\n", DestID);
printf("profile Version: %l\n", Pver);
printf("No of Profiles: %l\n", Profiles);
printf("Length: %l\n", Length);
printf("data : %l\n", Data);
}
if (close(newsockfd) == -1) {
error("Error closing connection with client 1");
}
printf("Connection with client 1 has been closed\n");
return 0;
}
The server is not showing any o/p. Client says it has send the packet. While compiling the server code i see four warnings saying unknown conversion type characters 0xa in format for all the printf statements in server code. I guess I am going wrong somewhere in the server code side, but I am not able to follow the "serialization". Please update me with your inputs, it would be of great help.
Here is couple of issues that I found:
Your client keep sending packages because it is in infinite while
loop.
You passed wrong len parameter of recv function. Right now
you pass sizeof(packet_size) which is equal to sizeof(long int) (4
bytes on 32 bit OS), but probably your intension was to use
sizeof(packet) (16 bytes).
You don't check how many bytes were
truly read by recv function. With TCP you don't have guaranties that
you read all 16 bytes of struct packet. So from time to time you
could read less bytes and your packet will be incomplete. Here is an
example in some pseudo code how you should receive whole packet:
bytes_to_receive = sizeof(packet)
received_bytes = 0;
do {
received_bytes += recv(buffer + received_bytes, bytes_to_receive - received_bytes)
} while (received_bytes != bytes_to_receive)
Your struct packet in client and server is different. In one you use char length; in second long int length;
I think also this kind of assignments in server make no sense pkt->srcID = SrcID; and should be something like this SrcID = pkt->srcID;
The problem with the client continually sending is because you simply have it in a loop. With indentation fixed, it becomes clear what has happened:
while (1)
{
if (send(sockfd,pkt,sizeof(packet_size),0) <0)
printf ("error\n");
else
printf ("packet send done");
}
addr_size = sizeof serverAddr;
connect(clientSocket, (struct sockaddr *) &serverAddr, addr_size);