Sending struct UDP socket twice instead of one - c++

I'm new to c++ and need help.
I use an UDP server to receive structure however i have problem to read it , the client send a structure I call : ChannAccessReq so the structure is send and the server receive it with RECVFROM and I use a general structure by reading the header (H1) of the struct only and then i do a read when a condition is fullfill with a more precise structure (temp2) for the buffer. However the client need to send the message twice , the first time it goes until recvfrom and the second it reach read() (i think) I tried all the day and wonder if its the size of the buffer ?
I think the most sensitive part is in the server with the recvfrom() who have a struct different from the read() just after..
I hope it's clear!
here is the server :
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <strings.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include "struct.h"
#include <iostream>
void DieWithError(char *err) {
perror(err);
exit(1);
}
typedef struct IntMsgHeaderType {
uint8_t code ; // Code message7
uint8_t bourrage ; // Octet de bourrage
uint16_t ParamLength; // Longueur eventuel données complémentaires
} HeaderInt;
typedef struct TextMessage //TESTTESTTEST
{
HeaderInt H; // Code message7
};
int main(int argc, char *argv[])
{
int sock; /* Socket */
struct sockaddr_in echoServAddr; /* Local address */
struct sockaddr_in echoClntAddr; /* Client address */
unsigned int cliAddrLen; /* Length of incoming message */
unsigned short echoServPort; /* Server port */
int recvMsgSize; /* Size of received message */
struct TextMessage * temp = (TextMessage *)malloc(sizeof(struct TextMessage));
HeaderInt *H1 =(HeaderInt *)malloc(104+sizeof(HeaderInt));
ChanAccesReq *temp2=(ChanAccesReq *)malloc(sizeof(ChanAccesReq));
if (!argv[1]) {
fprintf(stderr,"no port number provided");
exit(1);
}
echoServPort = atoi(argv[1]); /* First arg: local port */
/* Create socket for sending/receiving datagrams */
if ((sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
DieWithError("socket() failed");
/* Construct local address structure */
memset(&echoServAddr, 0, sizeof(echoServAddr)); /* Zero out structure */
echoServAddr.sin_family = AF_INET; /* Internet address family */
echoServAddr.sin_addr.s_addr = htonl(INADDR_ANY); /* Any incoming interface */
echoServAddr.sin_port = htons(echoServPort); /* Local port */
/* Bind to the local address */
if (bind(sock, (struct sockaddr *) &echoServAddr, sizeof(echoServAddr)) < 0)
DieWithError("bind() failed");
for (;;) /* Run forever */
{
cliAddrLen = sizeof(echoClntAddr);
int nbrOctet;
if (recvfrom(sock, H1, sizeof(*H1), 0,(struct sockaddr *) &echoClntAddr, &cliAddrLen)>0 && H1->code==1){
//read(sock,H1,sizeof(*H1));
std::cout<<"taille nbrOctet : "<<nbrOctet<<'\n';
memset(&echoServAddr, 0, sizeof(echoServAddr)); /* Zero out structure */
read(sock, temp2, sizeof(*temp2));
//read(sock,temp2,sizeof(*temp2))>0;
std::cout<<unsigned(temp2->P.linkAddr)<<'\n';
};
}
close(sock);
return 0;
}
and here the client
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <strings.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include "struct.h"
void DieWithError(char *err) {
perror(err);
exit(1);
}
typedef struct {
char transMode ;
uint8_t linkAddr;
} ChanAccessReqParam;
typedef struct {
HeaderInt H;
ChanAccessReqParam P;
} ChanAccesReq ;
int main(int argc, char *argv[])
{
int sock; /* Socket descriptor */
struct sockaddr_in echoServAddr; /* Echo server address */
struct sockaddr_in fromAddr; /* Source address of echo */
unsigned short echoServPort; /* Echo server port */
unsigned int fromSize; /* In-out of address size for recvfrom() */
char *servIP; /* IP address of server */
int structLen; /* Length of string to echo */
int respStringLen; /* Length of received response */
if (!argv[1]) {
fprintf(stderr,"No server IP sepcified at arg 1\n");
exit(1);
}
else if (!argv[2]) {
fprintf(stderr,"No port Number Sepcified at arg 2\n");
exit(2);
}
ChanAccesReq test { 1 ,1,0,'c',15};
servIP = argv[1]; /* First arg: server IP address (dotted quad) */
echoServPort = atoi(argv[2]); /* Use given port, if any */
/* Create a datagram/UDP socket */
if ((sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
DieWithError("socket() failed");
/* Construct the server address structure */
memset(&echoServAddr, 0, sizeof(echoServAddr)); /* Zero out structure */
echoServAddr.sin_family = AF_INET; /* Internet addr family */
echoServAddr.sin_addr.s_addr = inet_addr(servIP); /* Server IP address */
echoServAddr.sin_port = htons(echoServPort); /* Server port */
int tempint = 0;
tempint = sendto(sock, (ChanAccesInd*)&test, 10+(sizeof(test)), 0, (struct sockaddr *)
&echoServAddr, sizeof(echoServAddr));
if (tempint == -1 ) {
printf("Sent struct size: %d\n", tempint);
DieWithError("sendto() sent a different number of bytes than expected\n");
}
close(sock);
exit(0);
}
Thank you for your help

In C++ you have to define the type of the parameters.
As I deduced from the calling place, it should be int and bool.
int GesCanSlotSendTimeInd( int subscIPAddr , bool TransModeFlash){
return 0;
}
Also it is possible to use const qualifier, but you also need the type.
int GesCanSlotSendTimeInd( const int& subscIPAddr , const bool& TransModeFlash){
return 0;
}
For further info please look at cpp reference

You need to use non-blocking mode to poll for recvfrom and sendto at the same time. See here for more details.
int main(int argc, const char** argv) {
setvbuf(stdout, NULL, _IONBF, 0);
int portnum = 9988;
if (argc >= 2) {
portnum = atoi(argv[1]);
}
printf("Listening on port %d\n", portnum);
int sockfd = listen_inet_socket(portnum);
struct sockaddr_in peer_addr;
socklen_t peer_addr_len = sizeof(peer_addr);
int newsockfd = accept(sockfd, (struct sockaddr*)&peer_addr, &peer_addr_len);
if (newsockfd < 0) {
perror_die("ERROR on accept");
}
report_peer_connected(&peer_addr, peer_addr_len);
// Set nonblocking mode on the socket.
int flags = fcntl(newsockfd, F_GETFL, 0);
if (flags == -1) {
perror_die("fcntl F_GETFL");
}
if (fcntl(newsockfd, F_SETFL, flags | O_NONBLOCK) == -1) {
perror_die("fcntl F_SETFL O_NONBLOCK");
}
while (1) {
uint8_t buf[1024];
printf("Calling recv...\n");
int len = recv(newsockfd, buf, sizeof buf, 0);
if (len < 0) {
if (errno == EAGAIN || errno == EWOULDBLOCK) {
usleep(200 * 1000);
continue;
}
perror_die("recv");
} else if (len == 0) {
printf("Peer disconnected; I'm done.\n");
break;
}
printf("recv returned %d bytes\n", len);
}
close(newsockfd);
close(sockfd);
return 0;
}
"A couple of notable differences from the blocking version:
The newsockfd socket returned by accept is set to nonblocking mode by calling fcntl.
When examining the return status of recv, we check whether errno is set to a value saying that no data is available for receiving. In this case we just sleep for 200 milliseconds and continue to the next iteration of the loop."

You can still send() and recvfrom() on the same socket since that you dont really need 2 differents process if that's what you need

Related

Multipath udp connections

I programmed client and server codes. Both client and server have two interfaces and two separate IP addresses. To check the result, i made two tap loopbacks.
And then, i check the server and client. It seems that client is sending packets over both sockets but server only receives packets from one socket.
Could you please guide me what is the problem with my code or maybe the loopbaks?
client
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <string.h>
#include <iostream>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>
#include <netdb.h>
#include <sys/socket.h>
#define BUFLEN 2048
#define MSGS 5 /* number of messages to send */
int main(void)
{
struct sockaddr_in myaddr, remaddr;
int fd, i, slen=sizeof(remaddr);
char buf[BUFLEN]; /* message buffer */
int recvlen; /* # bytes in acknowledgement message */
char *server = "192.168.10.10"; /* change this to use a different server */
//////////////////////////////////
struct sockaddr_in myaddr2, remaddr2;
int fd2, slen2=sizeof(remaddr2);
char buf2[BUFLEN]; /* message buffer */
int recvlen2; /* # bytes in acknowledgement message */
char *server2 = "192.168.11.11"; /* change this to use a different server */
//////////////////////////////
/* create a socket */
if ((fd=socket(AF_INET, SOCK_DGRAM, 0))==-1)
printf("socket created\n");
/////////////////////////////
if ((fd2=socket(AF_INET, SOCK_DGRAM, 0))==-1)
printf("socket2 created\n");
/////////////////////////////
/* bind fd and fd2 */
memset((char *)&myaddr, 0, sizeof(myaddr));
myaddr.sin_family = AF_INET;
//myaddr.sin_addr.s_addr = htonl(INADDR_ANY);
inet_pton(AF_INET, "192.168.10.10", &myaddr.sin_addr.s_addr);
myaddr.sin_port = htons(2000);
/////////////////////////////
memset((char *)&myaddr2, 0, sizeof(myaddr2));
myaddr2.sin_family = AF_INET;
//myaddr.sin_addr.s_addr = htonl(INADDR_ANY);
inet_pton(AF_INET, "192.168.11.11", &myaddr2.sin_addr.s_addr);
myaddr2.sin_port = htons(2001);
/////////////////////////////
if (bind(fd, (struct sockaddr *)&myaddr, sizeof(myaddr)) < 0) {
perror("bind failed");
return 0;
}
/////////////////////////////
if (bind(fd2, (struct sockaddr *)&myaddr2, sizeof(myaddr2)) < 0) {
perror("bind2 failed");
return 0;
}
/////////////////////////////
// printf("binding ip %s to port %d\n", myaddr.sin_addr.s_addr, myaddr.sin_port);
/* now define remaddr, the address to whom we want to send messages */
/* For convenience, the host address is expressed as a numeric IP address */
/* that we will convert to a binary format via inet_aton */
memset((char *) &remaddr, 0, sizeof(remaddr));
remaddr.sin_family = AF_INET;
remaddr.sin_port = htons(3000);
if (inet_aton(server, &remaddr.sin_addr)==0) {
fprintf(stderr, "inet_aton() failed\n");
exit(1);
}
/////////////////////////////
memset((char *) &remaddr2, 0, sizeof(remaddr2));
remaddr2.sin_family = AF_INET;
remaddr2.sin_port = htons(4000);
if (inet_aton(server2, &remaddr2.sin_addr)==0) {
fprintf(stderr, "inet_aton2() failed\n");
exit(1);
}
/////////////////////////////
/* now let's send the messages */
for (i=0; i < MSGS; i++) {
printf("Sending packet %d to %s port %d\n", i, server, remaddr.sin_port);
sprintf(buf, "This is packet %d", i);
if (sendto(fd, buf, strlen(buf), 0, (struct sockaddr *)&remaddr, slen)==-1) {
perror("sendto");
exit(1);
}
printf("socket %i SENT A PACKET \n", fd);
printf("Sending packet %d to %s port %d\n", i, server2, remaddr2.sin_port);
sprintf(buf2, "This is packet %d", i);
if (sendto(fd2, buf2, strlen(buf2), 0, (struct sockaddr *)&remaddr2, slen2)==-1) {
perror("sendto2");
exit(1);
}
printf("socket %i SENT A PACKET \n", fd2);
}
close(fd);
close(fd2);
return 0;
}
server
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <string.h>
#include <errno.h>
#include <iostream>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/select.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <netdb.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#define BUFSIZE 2048
int
main(int argc, char **argv)
{
int n;
fd_set readfds;
struct timeval tv;
struct sockaddr_in myaddr; /* our address */
struct sockaddr_in remaddr; /* remote address */
socklen_t addrlen = sizeof(remaddr); /* length of addresses */
int recvlen; /* # bytes received */
int fd; /* our socket */
unsigned char buf[BUFSIZE]; /* receive buffer */
/////////////////////
struct sockaddr_in myaddr2; /* our address */
struct sockaddr_in remaddr2; /* remote address */
socklen_t addrlen2 = sizeof(remaddr2); /* length of addresses */
int recvlen2; /* # bytes received */
int fd2; /* our socket */
unsigned char buf2[BUFSIZE]; /* receive buffer */
/////////////////////
/* create a UDP socket */
if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
perror("cannot create socket\n");
return 0;
}
printf("socket %i is open \n", fd);
///////////////////////////////
if ((fd2 = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
perror("cannot create socket2\n");
return 0;
}
printf("socket %i is open \n", fd2);
///////////////////////////////
// clear the set ahead of time
FD_ZERO(&readfds);
// add our descriptors to the set
FD_SET(fd, &readfds);
FD_SET(fd2, &readfds);
// since we got s2 second, it's the "greater", so we use that for
// the n param in select()
n = fd2 + 1;
/* bind the socket to any valid IP address and a specific port */
memset((char *)&myaddr, 0, sizeof(myaddr));
myaddr.sin_family = AF_INET;
//myaddr.sin_addr.s_addr = htonl(INADDR_ANY);
inet_pton(AF_INET, "192.168.10.10", &myaddr.sin_addr.s_addr);
myaddr.sin_port = htons(3000);
if (bind(fd, (struct sockaddr *)&myaddr, sizeof(myaddr)) < 0) {
perror("bind failed");
return 0;
}
///////////////////////////
memset((char *)&myaddr2, 0, sizeof(myaddr2));
myaddr2.sin_family = AF_INET;
//myaddr2.sin_addr.s_addr = htonl(INADDR_ANY);
inet_pton(AF_INET, "192.168.11.11", &myaddr2.sin_addr.s_addr);
myaddr2.sin_port = htons(4000);
if (bind(fd2, (struct sockaddr *)&myaddr2, sizeof(myaddr2)) < 0) {
perror("bind2 failed");
return 0;
}
// wait until either socket has data ready to be recv()d (timeout 10.5 secs)
tv.tv_sec = 50;
tv.tv_usec = 500000;
for (;;) {
int rv = select(n, &readfds, NULL, NULL, &tv);
if (rv == -1) {
perror("select"); // error occurred in select()
} else if (rv == 0) {
printf("Timeout occurred! No data after 10.5 seconds.\n");
} else {
// one or both of the descriptors have data
if (FD_ISSET(fd, &readfds)) {
printf("socket %i RECEIVED A PACKET \n", fd);
printf("waiting on port %d\n", myaddr.sin_port);
recvlen = recvfrom(fd, buf, BUFSIZE, 0, (struct sockaddr *)&remaddr, &addrlen);
if (recvlen > 0) {
buf[recvlen] = 0;
printf("received message: \"%s\" (%d bytes)\n", buf, recvlen);
}
else
printf("uh oh - something went wrong!\n");
//sprintf(buf, "ack %d", msgcnt++);
}
if (FD_ISSET(fd2, &readfds)) {
printf("socket %i RECEIVED A PACKET \n", fd2);
printf("waiting on port %d\n", myaddr2.sin_port);
recvlen2 = recvfrom(fd2, buf2, BUFSIZE, 0, (struct sockaddr *)&remaddr2, &addrlen2);
if (recvlen2 > 0) {
buf[recvlen2] = 0;
printf("received message2: \"%s\" (%d bytes)\n", buf2, recvlen2);
}
else
printf("uh oh - something went wrong2!\n");
//sprintf(buf, "ack %d", msgcnt++);
}
}
}
}
result is shown in the picture:
================
Right now i checked the program in ns3 simulator network. It works correctly. so it seems that problem is with loopback. Please guide me how could i make loopback and test it over localhost.

Socket Server with Multiple clients. Killing child processes

I have been writing a server that supposed to work with multiple clients using fork().
I am closing the sockets and exiting the child processes, but after handling all the clients I end up with tons of child processes (Have checked it with ps -ef).
Am I missing something here?
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include "sbb_socket.h"
#include "bond_container.h"
#include <iostream>
#define SBB_ANY
void do_process(int sd_current);
int main(int argc, char* argv[])
{
/*
* get the number of clients from argument
*/
long client_count = 1;
if (argc > 1 && strtol(argv[1], NULL, 10) > 0) {
client_count = strtol(argv[1], NULL, 10);
}
pid_t pid;
int sd_current;
/*
* get an internet domain socket
*/
int sd;
if ((sd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("socket");
exit(1);
}
/*
* set up the socket structure
*/
struct sockaddr_in sock_addr;
memset(&sock_addr, 0, sizeof(sock_addr));
sock_addr.sin_family = AF_INET;
#ifdef SBB_ANY
/* set to INADDR_ANY if want server to be open to any client on any machine */
sock_addr.sin_addr.s_addr = INADDR_ANY;
#else
char hostname[128];
/*
* we'll default to this host and call a section 3 func to get this host
*/
if( gethostname(hostname,sizeof(hostname)) ){
fprintf(stderr," SBB gethostname(...) failed errno: %d\n", errno);
exit(1);
}
//printf("SBB gethostname() local hostname: \"%s\"\n", hostname);
/*
* set up socket structure for our host machine
*/
struct hostent *hp;
if ((hp = gethostbyname(hostname)) == 0) {
fprintf(stderr,"SBB gethostbyname(...) failed errno: %d exiting...\n", errno);
exit(1);
}
sock_addr.sin_addr.s_addr = ((struct in_addr *)(hp->h_addr))->s_addr;
#endif
sock_addr.sin_port = htons(PORT);
/*
* bind the socket to the port number
*/
if (bind(sd, (struct sockaddr *) &sock_addr, sizeof(sock_addr)) == -1) {
perror("bind");
exit(1);
}
/*
* advertise we are available on this socket/port
*/
if (listen(sd, 5) == -1) {
perror("listen");
exit(1);
}
while(1)
{
/*
* wait for a client to connect
*/
struct sockaddr_in sock_addr_from_client;
socklen_t addrlen = sizeof(sock_addr_from_client);
if ((sd_current = accept(sd, (struct sockaddr *) &sock_addr_from_client, &addrlen)) == -1) {
fprintf(stderr,"SBB accept(...) failed errno: %d exiting...\n", errno);
exit(1);
}
/*
* block on socket waiting for client message
*/
if ((pid = fork()) < 0) {
printf("Error on fork");
exit(1);
}
if (pid == 0) {
close(sd);
do_process(sd_current);
exit(0);
}
else {
close(sd_current);
}
}
}
The hanging child processes are probably zombie processes.
You could do for example following for avoiding problem:
Use waitpid() of wait() in parent process to get rid of zombies.
Use 'double fork' trick to put child processes under init process.

Client-server text file transfer using UDP & sockets in C++, server creates a blank file

First of all, I'd like to point out that i'm not a good programmer, so please be patient with me. The logic in the program is as follows: the client sends the server a text file, the server saves it under a different name. In short, very similar to this topic:
" File transfer server/client using socket " except that I'm using a different protocol. I think I've managed to succesfully send the file, but it seems like the server, afters creating a blank file, stucks in a loop/doesn't write anything in it.
Here's the code for the client:
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h> /* memset() */
#include <sys/time.h> /* select() */
#include <errno.h>
#include <sys/stat.h>
#include <fcntl.h>
#define REMOTE_SERVER_PORT 1500
#define MAX_MSG 100
#define PLIK "/home/aatami/Documents/programowanie/serwer/plik.txt"
#define LENGTH 512
int main(int argc, char *argv[]) {
int sd, rc, i,fd;
unsigned int cliLen;
struct sockaddr_in cliAddr, remoteServAddr;
struct hostent *h;
char buf[LENGTH];
/* check command line args */
if(argc<3) {
printf("usage : %s <server> <data1> ... <dataN> \n", argv[0]);
exit(1);
}
/* get server IP address (no check if input is IP address or DNS name */
h = gethostbyname(argv[1]);
if(h==NULL) {
printf("%s: unknown host '%s' \n", argv[0], argv[1]);
exit(1);
}
printf("%s: sending data to '%s' (IP : %s) \n", argv[0], h->h_name,
inet_ntoa(*(struct in_addr *)h->h_addr_list[0]));
remoteServAddr.sin_family = h->h_addrtype;
memcpy((char *) &remoteServAddr.sin_addr.s_addr,
h->h_addr_list[0], h->h_length);
remoteServAddr.sin_port = htons(REMOTE_SERVER_PORT);
/* socket creation */
sd = socket(AF_INET,SOCK_DGRAM,0); /* port 0 - system gets the first free one */
if(sd<0) {
printf("%s: cannot open socket \n",argv[0]);
exit(1);
}
/* bind any port */
cliAddr.sin_family = AF_INET;
cliAddr.sin_addr.s_addr = htonl(INADDR_ANY);
cliAddr.sin_port = htons(0);
rc = bind(sd, (struct sockaddr *) &cliAddr, sizeof(cliAddr));
if(rc<0) {
printf("%s: cannot bind port\n", argv[0]);
exit(1);
}
/* send data */
for(i=2;i<argc;i++) {
rc = sendto(sd, argv[i], strlen(argv[i])+1, 0,
(struct sockaddr *) &remoteServAddr,
sizeof(remoteServAddr));
if(rc<0) {
printf("%s: cannot send data %d \n",argv[0],i-1);
close(sd);
exit(1);
}
/* send text file */
char sdbuf[LENGTH];
printf("[Client] Sending %s to the Server... ", PLIK);
FILE *fs = fopen(PLIK, "r");
if(fs == NULL)
{
printf("ERROR: File %s not found.\n", PLIK);
exit(1);
}
bzero(sdbuf, LENGTH);
int fs_block_sz;
while((fs_block_sz = fread(sdbuf, sizeof(char), LENGTH, fs)) > 0)
{
if(send(sd, sdbuf, fs_block_sz, 0) < 0)
{
fprintf(stderr, "ERROR: Failed to send file %s. (errno = %d)\n", PLIK, errno);
break;
}
bzero(sdbuf, LENGTH);
}
printf("Ok File %s from Client was Sent!\n", PLIK);
}
return 1;
}
And the code for the server:
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h> /* close() */
#include <string.h> /* memset() */
#include <errno.h>
#define LENGTH 512
#define LOCAL_SERVER_PORT 1500
#define MAX_MSG 100
#define PLIKSERV "/home/aatami/Documents/programowanie/serwer/plikserv.txt"
int main(int argc, char *argv[]) { /* licznik argumentow, tablica argumentow */
int sd, rc,nsockfd;
unsigned int n,cliLen;
struct sockaddr_in cliAddr, servAddr;
char msg[MAX_MSG];
char buf[512],sbuf[LENGTH];
/* socket creation */
sd=socket(AF_INET, SOCK_DGRAM, 0);
if(sd<0) {
printf("%s: cannot open socket \n",argv[0]);
exit(1);
}
/* bind local server port */
servAddr.sin_family = AF_INET;
servAddr.sin_addr.s_addr = htonl(INADDR_ANY);
servAddr.sin_port = htons(LOCAL_SERVER_PORT);
rc = bind (sd, (struct sockaddr *) &servAddr,sizeof(servAddr));
if(rc<0) {
printf("%s: cannot bind port number %d \n",
argv[0], LOCAL_SERVER_PORT);
exit(1);
}
printf("%s: waiting for data on port UDP %u\n",
argv[0],LOCAL_SERVER_PORT);
/* server infinite loop */
while(1) {
/* init buffer */
memset(msg,0x0,MAX_MSG);
/* receive message */
cliLen = sizeof(cliAddr);
n = recvfrom(sd, msg, MAX_MSG, 0,
(struct sockaddr *) &cliAddr, &cliLen);
if(n<0) {
printf("%s: cannot receive data \n",argv[0]);
continue;
}
/* print received message */
printf("%s: from %s:UDP%u : %s \n",
argv[0],inet_ntoa(cliAddr.sin_addr),
ntohs(cliAddr.sin_port),msg);
unsigned int sin_size = sizeof(struct sockaddr_in);
FILE *fr = fopen(PLIKSERV, "a");
if(fr == NULL)
printf("File %s Cannot be opened file on server.\n", PLIKSERV);
else
{
bzero(sbuf, LENGTH);
int fr_block_sz = 0;
while((fr_block_sz = recvfrom(sd, buf, LENGTH, 0,(struct sockaddr *) &cliAddr, &cliLen)) > 0)
{
int write_sz = fwrite(buf, sizeof(char), fr_block_sz, fr);
if(write_sz < fr_block_sz)
{
perror("File write failed on server.\n");
}
bzero(buf, LENGTH);
if (fr_block_sz == 0 || fr_block_sz != 512)
{
break;
}
}
if(fr_block_sz < 0)
{
if (errno == EAGAIN)
{
printf("recv() timed out.\n");
}
else
{
fprintf(stderr, "recv() failed due to errno = %d\n", errno);
exit(1);
}
}
printf("Ok received from client!\n");
fclose(fr);
}
}/* end of server infinite loop */
return 0;
}
Any help greatly appreciated!
After seen your code I'd suggest try to send a "Hello world\n" from client to the server, see if you get it there. Once you make the connection between client and server then try to expand the code to do a file transfer.
But keep this in mind about UDP:
"UDP uses a simple transmission model with a minimum of protocol mechanism. It has no handshaking dialogues, and thus exposes any unreliability of the underlying network protocol to the user's program. As this is normally IP over unreliable media, there is no guarantee of delivery, ordering or duplicate protection. If error correction facilities are needed at the network interface level, an application may use the Transmission Control Protocol (TCP) which is designed for this purpose."
As you start the client, it sends all packets as fast as possible, could it be that the packets get lost or disordered or even duplicates at the server site. I also suggest waiting for a packet to acknowledge the correct reception. I mean, when then server receives a packet it sends a packet to acknowledge it to the client. This way, a conversation (dialog) could be held and the transfer accomplished satisfactory.

IPv6 Socket Program Problem

Seems that flow not going in " for" loop containing accept in ipv6server.c and hence not able to accept and connect with the client. Whats the mistake ? This code is working fine for IPV4 but after IPV6 changes getting this problem
ipv6server.c
#include <stdio.h>
#include <stdlib.h> /* needed for os x */
#include <string.h> /* for memset */
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/errno.h> /* defines ERESTART, EINTR */
#include <sys/wait.h> /* defines WNOHANG, for wait() */
#include "port.h" /* defines default port */
#ifndef ERESTART
#define ERESTART EINTR
#endif
extern int errno;
void serve(int port); /* main server function */
void disconn(void);
main(int argc, char **argv)
{
extern char *optarg;
extern int optind;
int c, err = 0;
int port = SERVICE_PORT;
static char usage[] = "usage: %s [-d] [-p port]\n";
while ((c = getopt(argc, argv, "dp:")) != -1)
switch (c) {
case 'p':
port = atoi(optarg);
if (port < 1024 || port > 65535) {
fprintf(stderr, "invalid port number: %s\n", optarg);
err = 1;
}
break;
case '?':
err = 1;
break;
}
if (err || (optind < argc)) {
fprintf(stderr, usage, argv[0]);
exit(1);
}
serve(port);
}
/* serve: set up the service */
void
serve(int port)
{
int svc; /* listening socket providing service */
int rqst; /* socket accepting the request */
socklen_t alen; /* length of address structure */
struct sockaddr_in6 my_addr; /* address of this service */
struct sockaddr_in6 client_addr; /* client's address */
int sockoptval = 1;
char hostname[128]; /* host name, for debugging */
gethostname(hostname, 128);
/* get a tcp/ip socket */
/* AF_INET is the Internet address (protocol) family */
/* with SOCK_STREAM we ask for a sequenced, reliable, two-way */
/* conenction based on byte streams. With IP, this means that */
/* TCP will be used */
if ((svc = socket(AF_INET6, SOCK_STREAM, 0)) < 0) {
perror("cannot create socket");
exit(1);
}
/* we use setsockopt to set SO_REUSEADDR. This allows us */
/* to reuse the port immediately as soon as the service exits. */
/* Some operating systems will not allow immediate reuse */
/* on the chance that some packets may still be en route */
/* to the port. */
setsockopt(svc, SOL_SOCKET, SO_REUSEADDR, &sockoptval, sizeof(int));
/* set up our address */
/* htons converts a short integer into the network representation */
/* htonl converts a long integer into the network representation */
/* INADDR_ANY is the special IP address 0.0.0.0 which binds the */
/* transport endpoint to all IP addresses on the machine. */
memset((char*)&my_addr, 0, sizeof(my_addr)); /* 0 out the structure */
my_addr.sin6_family = AF_INET6; /* address family */
my_addr.sin6_port = htons(port);
my_addr.sin6_addr = in6addr_any;
client_addr.sin6_family = AF_INET6; /* address family */
client_addr.sin6_port = htons(port);
client_addr.sin6_addr = in6addr_any;
/* bind to the address to which the service will be offered */
if (bind(svc, (struct sockaddr *)&my_addr, sizeof(my_addr)) < 0) {
perror("bind failed");
exit(1);
}
/* set up the socket for listening with a queue length of 5 */
if (listen(svc, 5) < 0) {
perror("listen failed");
exit(1);
}
printf("server started on %s, listening on port %d\n", hostname, port);
/* loop forever - wait for connection requests and perform the service */
alen = sizeof(client_addr); /* length of address */
for (;;) {
while ((rqst = accept(svc,
(struct sockaddr *)&client_addr, &alen)) < 0) {
/* we may break out of accept if the system call */
/* was interrupted. In this case, loop back and */
/* try again */
if ((errno != ECHILD) && (errno != ERESTART) && (errno != EINTR)) {
perror("accept failed");
exit(1);
}
}
printf("received a connection from: %s port %d\n",
inet_ntoa(client_addr.sin6_addr), ntohs(client_addr.sin6_port));
shutdown(rqst, 2); /* close the connection */
}
}
ipv6client.c
/*
echoc: a demo of TCP/IP sockets connect
usage: client [-h serverhost] [-p port]
*/
#include <stdio.h>
#include <stdlib.h> /* needed for os x*/
#include <string.h> /* for strlen */
#include <netdb.h> /* for gethostbyname() */
#include <sys/socket.h>
#include <netinet/in.h>
#include "port.h" /* defines default port */
int conn(char *host, int port);
void disconn(void);
main(int argc, char **argv)
{
extern char *optarg;
extern int optind;
int c, err = 0;
char *prompt = 0;
int port = SERVICE_PORT; /* default: whatever is in port.h */
char *host = "localhost"; /* default: this host */
static char usage[] =
"usage: %s [-d] [-h serverhost] [-p port]\n";
while ((c = getopt(argc, argv, "dh:p:")) != -1)
switch (c) {
case 'h': /* hostname */
host = optarg;
break;
case 'p': /* port number */
port = atoi(optarg);
if (port < 1024 || port > 65535) {
fprintf(stderr, "invalid port number: %s\n", optarg);
err = 1;
}
break;
case '?':
err = 1;
break;
}
if (err || (optind < argc)) { /* error or extra arguments? */
fprintf(stderr, usage, argv[0]);
exit(1);
}
printf("connecting to %s, port %d\n", host, port);
if (!conn(host, port)) /* connect */
exit(1); /* something went wrong */
disconn(); /* disconnect */
return 0;
}
int fd; /* fd is the file descriptor for the connected socket */
/* conn: connect to the service running on host:port */
/* return 0 on failure, non-zero on success */
int
conn(char *host, int port)
{
struct hostent *hp; /* host information */
unsigned int alen; /* address length when we get the port number */
struct sockaddr_in6 myaddr; /* our address */
struct sockaddr_in6 servaddr; /* server address */
printf("conn(host=\"%s\", port=\"%d\")\n", host, port);
/* get a tcp/ip socket */
/* We do this as we did it for the server */
/* request the Internet address protocol */
/* and a reliable 2-way byte stream */
if ((fd = socket(AF_INET6, SOCK_STREAM, 0)) < 0) {
perror("cannot create socket");
return 0;
}
/* bind to an arbitrary return address */
/* because this is the client side, we don't care about the */
/* address since no application will connect here --- */
/* INADDR_ANY is the IP address and 0 is the socket */
/* htonl converts a long integer (e.g. address) to a network */
/* representation (agreed-upon byte ordering */
memset((char *)&myaddr, 0, sizeof(myaddr));
myaddr.sin6_family = AF_INET6;
myaddr.sin6_addr = in6addr_any;
myaddr.sin6_port = htons(0);
if (bind(fd, (struct sockaddr *)&myaddr, sizeof(myaddr)) < 0) {
perror("bind failed");
return 0;
}
/* this part is for debugging only - get the port # that the operating */
/* system allocated for us. */
alen = sizeof(myaddr);
if (getsockname(fd, (struct sockaddr *)&myaddr, &alen) < 0) {
perror("getsockname failed");
return 0;
}
printf("local port number = %d\n", ntohs(myaddr.sin6_port));
/* fill in the server's address and data */
/* htons() converts a short integer to a network representation */
memset((char*)&servaddr, 0, sizeof(servaddr));
servaddr.sin6_family = AF_INET6;
servaddr.sin6_port = htons(port);
/* look up the address of the server given its name */
hp = gethostbyname(host);
if (!hp) {
fprintf(stderr, "could not obtain address of %s\n", host);
return 0;
}
/* put the host's address into the server address structure */
memcpy((void *)&servaddr.sin6_addr, hp->h_addr_list[0], hp->h_length);
/* connect to server */
if (connect(fd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) {
perror("connect failed");
return 0;
}
return 1;
}
/* disconnect from the service */
void
disconn(void)
{
printf("disconn()\n");
shutdown(fd, 2); /* 2 means future sends & receives are disallowed */
}
hp = gethostbyname(host);
How do you know this returns an IPv6 address if you pass it "localhost" ? It probably returns the IPv4 address, and things go belly up if you try to copy that into servaddr.sin6_addr
Use getaddrinfo() and explicitly look for an AF_INET6 address (or better yet, make your program independent of the actual address types, see here), or use the global in6addr_loopback as the server address, for testing with localhost.
I can see a few issues of varying degrees:
Don't declare errno yourself - use the headers. It may be a macro instead of an int
(per #Boofhead) don't bind the client socket
Use getaddrinfo() instead of gethostbyname() in the client to get the server's address. gethostbyname() doesn't portably support IPv6
The last of the 3 is actually the real problem. I've tested your code on MacOS X and CentOS 5 and gethostbyname() only returns an IPv4 address.

bad file descriptor with close() socket (c++)

I'm running out of file descriptors when my program can't connect another host. The close() system call doesn't work, the number of open sockets increases. I can se it with
cat /proc/sys/fs/file-nr
Print from console:
connect: No route to host
close: Bad file descriptor
connect: No route to host
close: Bad file descriptor
..
Code:
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <string.h>
#include <iostream>
using namespace std;
#define PORT 1238
#define MESSAGE "Yow!!! Are we having fun yet?!?"
#define SERVERHOST "192.168.9.101"
void
write_to_server (int filedes)
{
int nbytes;
nbytes = write (filedes, MESSAGE, strlen (MESSAGE) + 1);
if (nbytes < 0)
{
perror ("write");
}
}
void
init_sockaddr (struct sockaddr_in *name,
const char *hostname,
uint16_t port)
{
struct hostent *hostinfo;
name->sin_family = AF_INET;
name->sin_port = htons (port);
hostinfo = gethostbyname (hostname);
if (hostinfo == NULL)
{
fprintf (stderr, "Unknown host %s.\n", hostname);
}
name->sin_addr = *(struct in_addr *) hostinfo->h_addr;
}
int main()
{
for (;;)
{
sleep(1);
int sock;
struct sockaddr_in servername;
/* Create the socket. */
sock = socket (PF_INET, SOCK_STREAM, 0);
if (sock < 0)
{
perror ("socket (client)");
}
/* Connect to the server. */
init_sockaddr (&servername, SERVERHOST, PORT);
if (0 > connect (sock,
(struct sockaddr *) &servername,
sizeof (servername)))
{
perror ("connect");
sock = -1;
}
/* Send data to the server. */
if (sock > -1)
write_to_server (sock);
if (close (sock) != 0)
perror("close");
}
return 0;
}
Fix:
if (0 > connect (sock,
(struct sockaddr *) &servername,
sizeof (servername)))
{
perror ("connect");
}
else
write_to_server (sock);
if (close (sock) != 0)
perror("close");
It looks like the problem is in the structure of your program. Every time through your infinite loop, you're creating a new socket. I'd suggest moving this out of the loop and re-using it.
If you'd like to just fix the way you're doing it now though, use close inside the "connect" failed if statement you have now. The descriptor is allocated by the 'socket' call and only connected with the 'connect' call. By setting your 'sock' variable to -1, you're throwing away the descriptor allocated by 'socket'. Call close, then set it to -1 and you should be set.