Address family not supported by protocol UDP C Error sending - c

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()

Related

recvmsg() blocking on the first call but not on subsequent calls

I am having a problem with my client-server C program.
There are 2 main parts to the program. In part one, a message is sent from a Kernel module to a Userspace listener via multicast. I have tried and tested this part of the program many times and it works as expected.
The second part of the program transfers the message received to another machine (Machine 2). So, the Userspace listener from Machine 1 gets the message from the Kernel and then acts as a Client, opening up a socket between Machine 1 and Machine 2. The Server in Machine 2 receives the message and prints it to stdout. It then waits for another message.
The issue seems to be that the recvmsg() function blocks the first time but not in subsequent iterations. It is as if the information in the socket stays there and therefore prevents recvmsg() from blocking. The result is that the same piece of information is transferred in a loop.
I could be wrong on this recvmsg() problem. Perhaps someone has more experience and can point me in the right direction. The code and output are below. Many thanks.
NetLinkUser_Client.c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <linux/netlink.h>
#include <unistd.h>
#include <errno.h>
#include <unistd.h>
#include <netdb.h>
#include <netinet/in.h>
#define MAX_PAYLOAD 1024
#define MY_GROUP 1
#define OUT_PORT "5001"
#define OUT_IP "192.168.xxx.xxx"
void client(char *msg) {
int socketfd, portno, n;
struct sockaddr_in serv_addr;
struct hostent *server;
portno = atoi(OUT_PORT);
/* Create a socket point */
socketfd = socket(AF_INET, SOCK_STREAM, 0);
if (socketfd < 0) {
perror("ERROR opening socket");
exit(1);
}
server = gethostbyname(OUT_IP);
if (server == NULL) {
fprintf(stderr,"ERROR, no such host\n");
exit(0);
}
bzero((char *) &serv_addr, sizeof(serv_addr));
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);
/* Now connect to the server */
if (connect(socketfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) {
perror("ERROR connecting");
exit(1);
}
/* Now send a message to the server, this message
* will be read by server
*/
char buffer[MAX_PAYLOAD];
bzero(buffer,MAX_PAYLOAD);
strcpy(buffer, msg);
printf("\nThe contents of the buffer is: %s\n", buffer);
printf("\nThe length of the buffer is: %d\n", strlen(buffer));
/* Send message to the server */
n = write(socketfd, buffer, strlen(buffer));
if (n < 0) {
perror("ERROR writing to socket");
exit(1);
}
bzero(buffer,MAX_PAYLOAD);
printf("%s\n",buffer);
close(socketfd);
}
int main(void)
{
int sock_fd;
struct sockaddr_nl user_sockaddr;
struct nlmsghdr *nl_msghdr;
struct msghdr msghdr;
struct iovec iov;
char* kernel_msg;
sock_fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_USERSOCK);
if(sock_fd<0)
{
printf("Error creating socket because: %s\n", strerror(errno));
return -1;
}
memset(&user_sockaddr, 0, sizeof(user_sockaddr));
user_sockaddr.nl_family = AF_NETLINK;
user_sockaddr.nl_pid = getpid();
user_sockaddr.nl_groups = MY_GROUP;
bind(sock_fd, (struct sockaddr*)&user_sockaddr, sizeof(user_sockaddr));
while (1) {
ssize_t recvmsg_err = 0;
nl_msghdr = (struct nlmsghdr*) malloc(NLMSG_SPACE(1024));
memset(nl_msghdr, 0, NLMSG_SPACE(1024));
// The issue is not related to zeroing out msghdr
printf("The struct member msghdr.msg_namelen has the value : %d before zeroing out\n", msghdr.msg_namelen);
memset(&msghdr, 0, sizeof(msghdr));
printf("The struct member msghdr.msg_namelen has the value : %d after zeroing out\n", msghdr.msg_namelen);
memset(&iov, 0, sizeof(iov));
iov.iov_base = (void*) nl_msghdr;
iov.iov_len = NLMSG_SPACE(1024);
msghdr.msg_name = (void*) &user_sockaddr;
msghdr.msg_namelen = sizeof(user_sockaddr);
msghdr.msg_iov = &iov;
msghdr.msg_iovlen = 1;
printf("The struct member msghdr.msg_namelen has the value : %d after initialization\n", msghdr.msg_namelen);
printf("Waiting to receive message\n");
// Execution not pausing here WHY??
printf("recvmsg() should wait here\n");
recvmsg_err = recvmsg(sock_fd, &msghdr, 0);
if(recvmsg_err == -1)
{
perror("Error in recvmsg\n");
}
printf("The value returned by recvmsg() is %d\n", recvmsg_err);
kernel_msg = (char*)NLMSG_DATA(nl_msghdr);
printf("Kernel message: %s\n", kernel_msg); // print to android logs
client(kernel_msg);
}
close(sock_fd);
}
MsgServer.c
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <netdb.h>
#include <netinet/in.h>
#include <string.h>
#define MAX_PAYLOAD 1024
void doprocessing (int sock) {
int n;
char buffer[MAX_PAYLOAD];
bzero(buffer,MAX_PAYLOAD);
n = read(sock,buffer,MAX_PAYLOAD);
if (n < 0) {
perror("ERROR reading from socket");
exit(1);
}
printf("The length of the buffer is %d\n", strlen(buffer));
printf("Here is the message: %s\n",buffer);
}
int main( int argc, char *argv[] ) {
int sockfd, newsockfd, portno, clilen;
char buffer[1024];
struct sockaddr_in serv_addr, cli_addr;
int n, pid;
/* First call to socket() function */
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
perror("ERROR opening socket");
exit(1);
}
/* Initialize socket structure */
bzero((char *) &serv_addr, sizeof(serv_addr));
portno = 5001;
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
/* Now bind the host address using bind() call.*/
if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
perror("ERROR on binding");
exit(1);
}
/* Now start listening for the clients, here
* process will go in sleep mode and will wait
* for the incoming connection
*/
listen(sockfd,5);
clilen = sizeof(cli_addr);
while (1) {
printf("Waiting for initial connection in doProcessing() while loop\n");
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
if (newsockfd < 0) {
perror("ERROR on accept");
exit(1);
}
/* Create child process */
pid = fork();
if (pid < 0) {
perror("ERROR on fork");
exit(1);
}
if (pid == 0) {
/* This is the client process */
close(sockfd);
doprocessing(newsockfd);
exit(0);
}
else {
close(newsockfd);
}
} /* end of while */
}
Client sample output
The struct member msghdr.msg_namelen has the value : 12 before zeroing out
The struct member msghdr.msg_namelen has the value : 0 after zeroing out
The struct member msghdr.msg_namelen has the value : 12 after initialization
Waiting to receive message
recvmsg() should wait here
The value returned by recvmsg() is 72
Kernel message: Progger:7,root,1537,1533,1261,4s,192.168.xxx.xxx,5001
The contents of the buffer is: Progger:7,root,1537,1533,1261,4s,192.168.xxx.xxx,5001
The length of the buffer is: 54
The struct member msghdr.msg_namelen has the value : 12 before zeroing out
The struct member msghdr.msg_namelen has the value : 0 after zeroing out
The struct member msghdr.msg_namelen has the value : 12 after initialization
Waiting to receive message
recvmsg() should wait here
The value returned by recvmsg() is 72
Kernel message: Progger:7,root,1537,1533,1261,4s,192.168.xxx.xxx,5001
The contents of the buffer is: Progger:7,root,1537,1533,1261,4s,192.168.xxx.xxx,5001
The length of the buffer is: 54
Server Sample Output
Waiting for initial connection in doProcessing() while loop
The length of the buffer is 54
Here is the message: Progger:7,root,1537,1533,1261,4s,192.168.xxx.xxx,5001
Waiting for initial connection in doProcessing() while loop
The length of the buffer is 54
Here is the message: Progger:7,root,1537,1533,1261,4s,192.168.xxx.xxx,5001
Waiting for initial connection in doProcessing() while loop
The length of the buffer is 54
Here is the message: Progger:7,root,1537,1533,1261,4s,192.168.xxx.xxx,5001
Waiting for initial connection in doProcessing() while loop
The length of the buffer is 54
Here is the message: Progger:7,root,1537,1533,1261,4s,192.168.xxx.xxx,5001
I understand that this might be hard to reproduce considering Netlink is involved. Thanks in advance for your help and sorry for the long post.
Edit: I have changed the code to check for errors in recvmsg() as was suggested but the output is exactly the same.

C - Sending Modified String Over Sockets

I'm trying to send a modified string over sockets. The goal is to take a string from the client, add something to it, then send it back. The strings are passed in command line arguments. Right now, I can receive the message from the client, but for some reason my recvfrom function is returning -1 which causes the client to get hung up and not receive the sendto from the server. It seems like the server is modifying the string fine, but I can't get it to receive correctly on the other side. I have print statements in my code for testing purposes. The command line arguments for the client are server name, port number, string. The command line arguments for the server are port number, string to concatenate. Below is my code:
headerFiles.h:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <errno.h>
#include <signal.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>
#include <sys/wait.h>
server.c:
#include "headerFiles.h"
int main(int argc, char* argv[])
{
int s;
int len;
char buffer[256];
struct sockaddr_in servAddr;
struct sockaddr_in clntAddr;
int clntAddrLen;
int serverPort;
char catStringMeow[256];
serverPort = atoi(argv[1]);
strcpy(catStringMeow, argv[2]);
// Build local (server) socket address
memset(&servAddr, 0, sizeof(servAddr));
servAddr.sin_family = AF_INET;
servAddr.sin_port = htons(serverPort);
servAddr.sin_addr.s_addr = htonl(INADDR_ANY);
// Create socket
if((s = socket(PF_INET, SOCK_DGRAM, 0)) < 0)
{
perror("Error: socket failed!");
exit(1);
}
// Bind socket to local address and port
if((bind(s, (struct sockaddr*)&servAddr, sizeof(servAddr)) < 0))
{
perror("Error: bind failed!");
exit(1);
}
for(;;) // Runs forever
{
printf("buffer = %s\n", buffer);
printf("In for\n");
// Receive String
len = recvfrom(s, buffer, sizeof(buffer), 0, (struct sockaddr*)&clntAddr, &clntAddrLen);
printf("Received %d bytes\n", len);
printf("buffer = %s\n", buffer);
strcat(buffer, " ");
strcat(buffer, catStringMeow);
printf("New string = %s\n",buffer);
printf("buffer size = %d\n", (int)strlen(buffer));
len = (int)strlen(buffer);
// Send String
sendto(s, buffer, len, 0, (struct sockaddr*)&clntAddr, sizeof(clntAddr));
printf("Sent %d bytes\n", len);
}
}
client.c:
#include "headerFiles.h"
int main (int argc, char* argv[]) // Three arguments to be checked later
{
int s; // Socket descriptor
int len; // Length of string to be echoed
char* servName; // Server name
int servPort; // Server port
char* string; // String to be echoed
char buffer[256+1]; // Data buffer
struct sockaddr_in servAddr; // Server socket address
// Check and set program arguments
if(argc != 4)
{
printf("Error: three arguments are needed!\n");
exit(1);
}
servName = argv[1];
servPort = atoi(argv[2]);
string = argv[3];
// Build server socket address
memset(&servAddr, 0, sizeof(servAddr));
servAddr.sin_family = AF_INET;
inet_pton(AF_INET, servName, &servAddr.sin_addr);
servAddr.sin_port = htons(servPort);
// Create socket
if((s = socket(PF_INET, SOCK_DGRAM, 0)) < 0)
{
perror("Error: Socket failed!");
exit(1);
}
// Send echo string
len = sendto(s, string, strlen(string), 0, (struct sockaddr*) &servAddr, sizeof(servAddr));
printf("Sent %d bytes\n", len);
// Receive echo string
len = recvfrom(s, buffer, len, 0, NULL, NULL);
printf("Received\n");
//Print and verify echoed string
buffer[len] = '\0';
printf("Echo string received: ");
fputs(buffer, stdout);
printf("\n");
// Close the socket
close(s);
// Stop the program
exit(0);
}
do
// Receive echo string
len = recvfrom(s, buffer, sizeof(buffer), 0, NULL, NULL);
printf("Received\n");
and make buffer bigger.
You're passing an uninitizlied clntAddrLen value to recvfrom, which is resulting in the Invalid argument error code. According to the documentation:
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.
So you need to initialize it with:
clntAddrLen = sizeof(clntAddr);
Make sure you initialize the client address length variable before using it in sendto or recvfrom.
The problem is that on the first calling to sendto from client.c, the servers sees the client's ip as 0.0.0.0, after that on the second, third,... calls the client.c get an ip and have a legal ip such as 127.0.0.3:3212.
You can see that second, third, ... clients work.
Initialize length variable to sizeof(struct sockaddr_in)

Linux C socket - keep server alive

I'm using C to implement a simple client-server retrieval system with Linux socket. I've now successfully connect the remote server, but when I close the connection, the server went down, i.e. the server program stopped.
What should I do avoid this?
here's sample of my code:
server:
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <netinet/in.h>
int main(void)
{
int optval;
socklen_t optlen = sizeof(optval);
char str[100] = "";
int listen_fd, conn_fd;
struct sockaddr_in servaddr;
listen_fd = socket(AF_INET, SOCK_STREAM, 0);
// check if on
getsockopt(listen_fd, SOL_SOCKET, SO_KEEPALIVE, &optval, &optlen);
printf("keep alive is %s\n", (optval? "ON" : "OFF"));
// set it on
optval = 1;
optlen = sizeof(optval);
setsockopt(listen_fd, SOL_SOCKET, SO_KEEPALIVE, &optval, optlen);
printf("done, check again.\n");
printf("keep alive is %s\n", (optval? "ON" : "OFF"));
bzero( &servaddr, sizeof(servaddr));
// set appropriate protocol and port number (15792)
// the htons() function converts the unsigned short integer
// from host byte order to network byte order.
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htons(INADDR_ANY);
servaddr.sin_port = htons(15792);
// Bind a name to a socket
bind(listen_fd, (struct sockaddr *) &servaddr, sizeof(servaddr));
// listening for incoming connection
listen(listen_fd, 10);
// accept a connection on a socket
conn_fd = accept(listen_fd, (struct sockaddr*) NULL, NULL);
do
{
// set str to null
bzero(str, 100);
// Read from a file descriptor (linux all)
read(conn_fd,str,100);
// print the received message
// printf("Received: %s\n",str);
if (!strcmp(str, "GET TIME\n"))
{
bzero(str, 100);
time_t clocks;
clocks = time(NULL);
sprintf(str, "%s", ctime(&clocks));
write(conn_fd, str, strlen(str));
//close(conn_fd);
}
else
{
bzero(str, 100);
strcpy(str, "ERROR: No such command.\n");
write(conn_fd, str, strlen(str));
//close(conn_fd);
}
} while (1);
}
client:
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc,char **argv)
{
// declare necessary variables
int sockfd;
char recv[1024] = "";
char command[100] = "";
struct sockaddr_in servaddr;
if (argc != 2)
{
printf("usage: %s <ip address>\n", argv[0]);
exit(EXIT_FAILURE);
}
// create a socket with the appropriate protocol
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
printf("ERROR: Failed create cosket.\n");
exit(EXIT_FAILURE);
}
// Set all the socket structures with null values.
bzero(&servaddr, sizeof servaddr);
// set appropriate protocol and port number (1999)
// The htons() function converts the unsigned short integer
// hostshort from host byte order to network byte order.
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(15792);
// Convert IPv4 and IPv6 addresses from text to binary form
if (inet_pton(AF_INET, argv[1], &(servaddr.sin_addr)) <= 0)
{
printf("ERROR: Wrong ip address.\n");
exit(EXIT_FAILURE);
}
// attempt to connect to a socket
if (connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0)
{
printf("ERROR: Failed at connect.\n");
exit(EXIT_FAILURE);
}
else
{
printf("------ connect successfull ------\n");
}
do
{
printf("> ");
fgets(command, 100, stdin);
write(sockfd, command, strlen(command));
if (!strcmp(command, "QUIT\n"))
{
close(sockfd);
break;
}
// print the receive stuff
read(sockfd, recv, sizeof(recv));
fputs(recv, stdout);
bzero(recv, 1024);
} while (1);
}
In your server code, the accept() function must be called in the do-while loop:
// listening for incoming connection
listen(listen_fd, 10);
do
{
// accept a connection on a socket
conn_fd = accept(listen_fd, (struct sockaddr*) NULL, NULL);
...
close(conn_fd);
} while(1);
my question here is, why server ended if I close the connection from
the client.
Because then the blocking read call will return the value 0 indicating the connection was closed, which you promptly ignore. You then try (and fail) to compare the received data (which you have none) to the string and you will attempt to write the error message to the (now disconnected) client which will raise the SIGPIPE error which terminates your application.
– Some programmer dude

Socket arbitrarily connects - or doesnt

I'm working on a university project, in which I have to connect a raspberry pi to an Android smartphone to control 2 motors.
We are new to socket programming, so we started out with an example we found on wikibooks and tried to modify in to our needs. We're now facing the problem, that the connection between server and client is very arbitrary and unstable, sometimes connecting, and after a brief disconnect doesnt connect again. The weird thing (for me) is, that after we edit the code above the part responsible for connection:
/* bind serv information to mysocket */
bind(mysocket, (struct sockaddr *)&serv, sizeof(struct sockaddr));
/* start listening, allowing a queue of up to 2 pending connection */
listen(mysocket, 2);
consocket = accept(mysocket, (struct sockaddr *)&dest, &socksize);
like inserting in a printf, the next time we launch the programm, everthing does work, sometimes two or three times, and then it just stops connecting.
I've searched all over google and so for a similar problem, but I haven't found an equivalent, so I turn to you directly now.
This is code for our server running on the raspberry pi, which also serves as a network hotspot:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <bcm2835.h>
#define PORTNUM 5298
#define MAXRCVLEN 1000
#define PIN9 RPI_GPIO_P1_21
#define PIN10 RPI_GPIO_P1_19
#define PIN11 RPI_GPIO_P1_23
#define PIN22 RPI_GPIO_P1_15
int setpins();
int forward();
int backward();
int main(int argc, char *argv[])
{
char msg[] = "Connected!\n";
char testchar[] = "stillthere?";
char quitstring[] = "quit";
char *recbuf;
int qflag = 0;
int lflag = 0;
int mysocket, consocket, len; /* socket used to listen for incoming connections */
struct sockaddr_in dest; /* socket info about the machine connecting to us */
struct sockaddr_in serv; /* socket info about our server */
socklen_t socksize = sizeof(struct sockaddr_in);
memset(&serv, 0, sizeof(serv)); /* zero the struct before filling the fields */
serv.sin_family = AF_INET; /* set the type of connection to TCP/IP */
serv.sin_addr.s_addr = htonl(INADDR_ANY); /* set our address to any interface */
serv.sin_port = htons(PORTNUM); /* set the server port number */
mysocket = socket(AF_INET, SOCK_STREAM, 0);
/* bind serv information to mysocket */
bind(mysocket, (struct sockaddr *)&serv, sizeof(struct sockaddr));
/* start listening, allowing a queue of up to 2 pending connection */
listen(mysocket, 2);
consocket = accept(mysocket, (struct sockaddr *)&dest, &socksize);
if (!bcm2835_init()) return 1;
setpins();
while(consocket)
{
printf("Incoming connection from %s - sending welcome\n", inet_ntoa(dest.sin_addr));
send(consocket, msg, strlen(msg), 0);
while (!qflag && !lflag) {
// Do something when connection is lost: SO_KEEPALIVE?
// if (!send(consocket,testchar, strlen(testchar), 0)) lflag = 1;
recbuf = malloc (MAXRCVLEN+1);
len = recv(consocket, recbuf, MAXRCVLEN, 0);
recbuf[len] = '\0';
if (len > 0) printf("Client sent %s (%d bytes). \n", recbuf, len);
if (recbuf[0] == 'v') forward(); // this function lets our car drive forward
if (recbuf[0] == 'r') backward();// this one backwards ;)
// Leave this loop if the client sends you the quitstring
if (!strcmp (recbuf, quitstring)) qflag = 1;
free(recbuf);
}
if (qflag) break;
listen(mysocket, 1);
consocket = accept(mysocket, (struct sockaddr *)&dest, &socksize);
}
close(consocket);
close(mysocket);
printf("sockets closed\n");
return EXIT_SUCCESS;
}
One line in there
// if (!send(consocket,testchar, strlen(testchar), 0)) lflag = 1;
is our idea to test wether the connection is still up, is this viable?
And this is the client code, thats not in Java yet but in C:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#define MAXRCVLEN 500
#define PORTNUM 5298
int main(int argc, char *argv[])
{
char buffer[MAXRCVLEN + 1]; /* +1 so we can add null terminator */
int len, mysocket;
struct sockaddr_in dest;
mysocket = socket(AF_INET, SOCK_STREAM, 0);
memset(&dest, 0, sizeof(dest)); /* zero the struct */
dest.sin_family = AF_INET;
dest.sin_addr.s_addr = inet_addr("192.168.42.1"); /* set destination IP number */
dest.sin_port = htons(PORTNUM); /* set destination port number */
do {
connect(mysocket, (struct sockaddr *)&dest, sizeof(struct sockaddr));
len = recv(mysocket, buffer, MAXRCVLEN, 0);
}while(len < 0);
/* We have to null terminate the received data ourselves */
buffer[len] = '\0';
// Received
printf("Received %s (%d bytes).\n", buffer, len);
// send:
char msg[] = " ";
do{
scanf("%s",msg);
printf("Sending Msg to %s \n", inet_ntoa(dest.sin_addr));
send( mysocket, msg, strlen(msg),0);
}while (strcmp(msg,"quit"));
close(mysocket);
return EXIT_SUCCESS;
}
Any ideas what we did wrong?
Thanks in advance!
Unless what you actually, really want to learn is low-level berkeley socket manipulation, I'd suggest you look at libevent or a similar library.
The structure of your main loop is a little unusual. You can clearly only handle one connection at a time, and you don't cope well with any connection attempts that happened while you were servicing a previous connection.
bind(mysocket, (struct sockaddr *)&serv, sizeof(struct sockaddr));
bind can fail, e.g. if another process has recently had the socket open and the OS hasn't finished cleaning up use of the port. You can change this behavior, but you should still check, from die.net's bind manpage
Return Value
On success, zero is returned. On error, -1 is returned, and errno is set appropriately.
so
if(bind(mysocket, (struct sockaddr *)&serv, sizeof(struct sockaddr))) {
perror("bind failed");
exit(1);
}
listen() only needs to be called once, but also needs to be checked
if(listen(mysocket, 2)) {
perror("listen failed");
exit(1);
}
after this, if you are content to do the single-service approach, then you can do the following:
mysocket = socket(AF_INET, SOCK_STREAM, 0);
if(mysocket < 0) {
perror("socket failed");
exit(1);
}
if(bind(mysocket, (struct sockaddr *)&serv, sizeof(struct sockaddr))) {
perror("bind failed");
exit(1);
}
if(listen(mysocket, 2)) {
perror("listen failed");
exit(1);
}
for (;;) {
consocket = accept(mysocket, (struct sockaddr *)&dest, &socksize);
if(consocket < 0) // might return if the connection has already gone away.
continue;
if (!sendGreeting(consocket)) {
// sendGreeting should return -1 if it was unable to send, 0 if successful
while (!readLoop(consocket, recvBuf, MAXRCVLEN))
;
}
close(consocket);
}
readLoop would then be something like:
int readLoop(int socket, char* buffer, size_t bufSize) {
int len = recv(socket, buffer, bufSize);
if (len > 0)
return processBuffer(socket, buffer, len);
if (len < 0 && (errno == EINTR || errno == EAGAIN))
return 0; // do-over
return -1;
}
make sure that processBuffer also returns 0 or -1 accordingly.
As I mentioned above, there are still problems with this approach, but it's not my intent here to teach you everything you need to know about sockets in one pass :) If you want to further develop your socket knowledge, your next stop should be learning about select or poll with non-blocking sockets so that you can host multiple sockets and service them as they become active.
Generally, you should use tcpdump/wireshark to see what packets are seen by you Rpi, and strace to see what your program does. My first guess about your connections sometimes not working would be loss of packets. By using wired LAN (Ethernet), you could rule this possibility out.
But the example server code that you're using is a rather bad example. Even if you only want to accept a single client connection at a time, your server should not use blocking waits for any remote message. You should read about using non-blocking I/O, select or poll, and look at examples using these. Also, please read about SO_REUSEADDR, you probably need that one in your server as well.
This line code
char msg[] = " ";
do{
scanf("%s",msg);
will fail miserably if the number of bytes scanned in is larger then 1 character, as msg provides exactly two bytes (from which one is always used as 0-terminator). Feeding more would write out of the bounds of msg and doing so will provoke undefined behaviuor.
To fix this providing at least a minimum of 255 characters to so:
char msg[256] = "";
do{
scanf("%255s",msg);

Problem in udp socket programing in c

I complile the following C code of UDP client
after I run './udpclient localhost 9191' in terminal.I put "Enter Text= " as Hello, but it is showing error in sendto as below:
Enter text: hello
hello
: error in sendto()guest-1SDRJ2#md-K42F:~/Desktop$
"
Note: I open 1st the server port as below in other terminal
./server 9191.
I beleive there is no error in server code. The udp client is not passing message to server. If I don't use thread , the message is passing .But I have to do it by thread.
UDP client Code:
/* simple UDP echo client */
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdio.h>
#include <pthread.h>
#define STRLEN 1024
static void *readdata(void *);
static void *writedata(void *);
int sockfd, n, slen;
struct sockaddr_in servaddr;
char sendline[STRLEN], recvline[STRLEN];
int main(int argc, char *argv[]) {
pthread_t readid,writeid;
struct sockaddr_in servaddr;
struct hostent *h;
if(argc != 3) {
printf("Usage: %s <proxy server ip> <port>\n", argv[0]);
exit(0);
}
/* create hostent structure from user entered host name*/
if ( (h = gethostbyname(argv[1])) == NULL) {
printf("\n%s: error in gethostbyname()", argv[0]);
exit(0);
}
/* create server address structure */
bzero(&servaddr, sizeof(servaddr)); /* initialize it */
servaddr.sin_family = AF_INET;
memcpy((char *) &servaddr.sin_addr.s_addr, h->h_addr_list[0], h->h_length);
servaddr.sin_port = htons(atoi(argv[2])); /* get the port number from argv[2]*/
/* create a UDP socket: SOCK_DGRAM */
if ( (sockfd = socket(AF_INET,SOCK_DGRAM, 0)) < 0) {
printf("\n%s: error in socket()", argv[0]);
exit(0);
}
pthread_create(&readid,NULL,&readdata,NULL);
pthread_create(&writeid,NULL,&writedata,NULL);
while(1)
{
};
close(sockfd);
}
static void * writedata(void *arg)
{
/* get user input */
printf("\nEnter text: ");
do {
if (fgets(sendline, STRLEN, stdin) == NULL) {
printf("\n%s: error in fgets()");
exit(0);
}
/* send a text */
if (sendto(sockfd, sendline, sizeof(sendline), 0, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0) {
printf("\n%s: error in sendto()");
exit(0);
}
}while(1);
}
static void * readdata(void *arg)
{
/* wait for echo */
slen = sizeof(servaddr);
if ( (n = recvfrom(sockfd, recvline, STRLEN, 0, (struct sockaddr *) &servaddr, &slen)) < 0) {
printf("\n%s: error in recvfrom()");
exit(0);
}
/* null terminate the string */
recvline[n] = 0;
fputs(recvline, stdout);
}
The problem is that you're using the same sockaddr struct (servaddr) for both the sendto and revfrom calls. The recvfrom happens first, so it clears out servaddr in preparation for writing in the source address of the received packed (once it receives one -- that thread is still blocked in the kernel waiting for a packet). Then, when the sendto call occurs, the sockaddr is all zeros, so it immediately returns EINVAL.
You may be getting confused by the fact that the sockaddr argument to recvfrom is an OUTPUT, not an input -- it gets filled in with the source address of the packet that is received (which could be from anywhere). If you want to only receive packets from a particular place (the server?), you need to check the address after the recvfrom returns and toss the packet if it comes from somewhere else, looping back to recvfrom again.

Resources