Udp server sending only 0 bytes of data - c++

This is a simple Udp server.I am trying to transmit data to some clients,but unfortunetly it is unable to transmit data.Though send is running quite successfully but it is returning with a return value meaning it has send nothing.On the client they are receiving but again obviously,zero bytes.
void* UdpServerStreamToClients(void *fileToServe)
{
int sockfd,n=0,k;
struct sockaddr_in servaddr,cliaddr;
socklen_t len;
char dataToSend[1000];
sockfd=socket(AF_INET,SOCK_DGRAM,0);
bzero(&servaddr,sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr=htonl(INADDR_ANY);
servaddr.sin_port=htons(32000);
bind(sockfd,(struct sockaddr *)&servaddr,sizeof(servaddr));
FILE *fp;
if((fp=fopen((char*)fileToServe,"r"))==NULL)
{
printf("can not open file ");
perror("fopen");
exit(1);
}
int dataRead=1;
while(dataRead)
{
len = sizeof(cliaddr);
if((dataRead=fread(dataToSend,1,500,fp))<0)
{
perror("fread");
exit(1);
}
//sleep(2);
for(list<clientInfo>::iterator it=clients.begin();it!=clients.end();it++)
{
cliaddr.sin_family = AF_INET;
inet_aton(inet_ntoa(it->addr.sin_addr),&cliaddr.sin_addr);
cliaddr.sin_port = htons(it->udp_port);
n=sendto(sockfd,dataToSend,sizeof(dataToSend),0,(struct sockaddr *)&cliaddr,len);
cout<<"number of bytes send by udp: "<< n << endl;
printf("SEND this message %d : %s to %s :%d \n",n,dataToSend,inet_ntoa(cliaddr.sin_addr), ntohs(cliaddr.sin_port));
}
}
}
I am checking the value of sizeof(dataTosend) and it is pretty much as expected ie thousand ie the size of buffer.
Are you people seeing some possible flaw in it.
All of the help in this regard will be appreciated.
Thanks!

Not sure this is the exact answer, but you forgot to memset() (or bzero()) the cliaddr structure before using it.
Also, the line:
inet_aton(inet_ntoa(it->addr.sin_addr),&cliaddr.sin_addr);
Could probably be written:
cliaddr.sin_addr = it->addr.sin_addr;

Related

Getting an error wile trying to open a TCP socket - c++

I'm trying to build a block that acts as server and client to send and receive data (2 duplicate versions in 2 different computers) through a TCP connection.
This is what I did and I'm trying to test using the windows commandd line "netstat -ab" to try to find the tcp connection but I can't find it.
Apart from the given error, what am i doing wrong?
bool IPTunnel::runBlock(void) {
int ready =
inputSignals[0]->ready(); // int ready2 = inputTCPConnetion[0]->ready();
// server
SOCKET sockfd, newsockfd;
int portno;
socklen_t clilen;
char buffer[256];
struct sockaddr_in serv_addr, cli_addr;
SOCKET n;
// create a socket(int domain, int type, int protocol)
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd < 0) printf("\n ERROR opening socket");
// bzero((char *)&serv_addr, sizeof(serv_addr));
portno = 5500;
serv_addr.sin_family = AF_INET;
char ipad[10] = "127.0.0.1";
serv_addr.sin_addr.s_addr = *ipad; // INADDR_ANY;
serv_addr.sin_port = htons(portno);
// if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
auto sd = bind(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
// if (sd < 0)
// printf("\n ERROR on binding");
listen(sockfd, 5);
clilen = sizeof(cli_addr);
newsockfd = accept(sockfd, (struct sockaddr*)&cli_addr, &clilen);
if(newsockfd < 0) printf("ERROR on accept");
printf("server: got connection from %s port %d\n",
inet_ntop(serv_addr.sin_family, &ipad, buffer, clilen),
ntohs(cli_addr.sin_port));
send(newsockfd, "Hello, world!\n", 13, 0);
// bzero(buffer, 256);
n = _read(newsockfd, buffer, 255);
if(n < 0) printf("ERROR reading from socket");
printf("Here is the message: %s\n", buffer);
while(true) {
}
// close(newsockfd);
// close(sockfd);
return 0;
}
This is the error that gives: Unhandled exception at 0x00007FFE5031B7EC (ucrtbased.dll) in ip_tunnel.exe: An invalid parameter was passed to a function that considers invalid parameters fatal.
in the _read function...
Well, this line is definitely wrong:
serv_addr.sin_addr.s_addr = *ipad; //INADDR_ANY;
If you want to receive incoming TCP connections on the loopback device, you should do something more like this:
serv_addr.sin_addr.s_addr = inet_aton("127.0.0.1");
(or if you want them to be received from any connected network device, specify INADDR_ANY instead)
Also, make sure you called WSAStartup() at the beginning of your program, Windows sockets won't work correctly if you haven't done that.
One last nitpick:
while(true){}
is not a good way to pause execution of your program. For one thing, it will typically spin a CPU at 100% usage, which is very inefficient, and for another, it invokes undefined behavior according to the C++ standard.
A better way to do get that behavior would be something like:
while(true) {Sleep(1000);}
Also this part is wrong/weird:
SOCKET n;
[...]
n = _read(newsockfd, buffer, 255);
... in that _read doesn't return a SOCKET, it returns an int. I think you meant to declare int n; instead.
One last potential problem: if your call to bzero(buffer, 256); is commented out, then it's quite possible for buffer to contain no zero-bytes after the _read() call returns, in which case your printf("Here is the message: %s\n", buffer); call afterwards could read right past the end of the buffer array and out into the wild blue yonder of other memory, potentially causing a crash (or at least causing a lot of garbage bytes to be printed). The fix is to make sure the buffer array contains a 0/NUL byte at the end of the valid bytes that were placed there by the _read() call.

Unable to receive full integer array through UDP socket in C [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
Here's my sender side code
void send_data(int port, int coords[4]){
struct sockaddr_in si_me, si_other;
int s, i, slen = sizeof(si_other), recv_len;
char buf[BUFLEN];
//create a UDP socket
if((s=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1){
err_print("socket");
}
//zero out the structure
memset((char*)&si_me, 0, sizeof(si_me));
si_me.sin_family = AF_INET;
si_me.sin_port = htons(port);
si_me.sin_addr.s_addr = htonl(INADDR_ANY);
//bind socket to the port
if(bind(s, (struct sockaddr *)&si_me, sizeof(si_me) ) == -1){
err_print("bind");
}
int size = sizeof(coords);
printf("Size: %d\n", size);
//Keep listening for data
while(1){
printf("Waiting for Data\n");
fflush(stdout);
memset(buf, 0, BUFLEN);
//try to receive some data, this is a blocking call
if((recv_len = recvfrom(s, buf, BUFLEN, 0, (struct sockaddr*) &si_other, &slen)) == -1){
err_print("recvfrom()");
}
//print details of the client/peer and the data received
printf("Received packet from %s:%d\n", inet_ntoa(si_other.sin_addr), ntohs(si_other.sin_port));
printf("%s\n", buf);
if(!strcmp(buf, "coords")) {
printf("Sending Coordinates: \n");
//now reply the client with the same data
int siz = sendto(s, coords, sizeof(coords), 0, (struct sockaddr*) &si_other, slen);
if(siz == -1){
err_print("sendto()");
}
printf("Siz: %d\n", siz);
}
break;
}
}
close(s);
}
The value returned from sendto is 8 which is the correct size of the int array but at the receiver side recvfrom returns 0 although the array receives the first two integer elements and the rest is garbage values when I print the array. Here's the receiver side code:
void get_data(int port, int coords[]){
struct sockaddr_in si_other;
int s, i;
char message[BUFLEN];
if((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1){
err_print("socket");
}
memset((char*)&si_other, 0, sizeof(si_other));
si_other.sin_family = AF_INET;
si_other.sin_port = htons(port);
si_other.sin_addr.s_addr = inet_addr(SERVER);
if(inet_aton(SERVER, &si_other.sin_addr) == 0){
fprintf(stderr, "inet_aton() failed\n");
exit(1);
}
socklen_t slen = sizeof(si_other);
int size = sizeof(coords);
printf("Size: %d\n", size);
int siz = 0;
while(1)
{
printf("Enter message : ");
strcpy(message, "coords");
//send the message
if (sendto(s, message, strlen(message) , 0 , (struct sockaddr *) &si_other, slen)==-1)
{
err_print("sendto()");
}
//try to receive some data, this is a blocking call
if (siz = (recvfrom(s, coords, 8, 0, (struct sockaddr *) &si_other, &slen)) == -1)
{
err_print("recvfrom()");
}
printf("Siz: %d\n", siz);
break;
}
for(int j = 0; j<4; j++){
printf("C: %d\n", coords[j]);
}
close(s);
return;
}
And the output of coords array is on the receiver side : 1 2 4196592 0
Now, i thought perhaps, the whole array wasnt getting sent, but the size values returned by sendto is 8 and that of recvfrom is 0 even if it gets the first two elements right. Also, do note that on compilation, I get warning for sizeof:
‘sizeof’ on array function parameter ‘coords’ will return size of ‘int *’
What could be wrong here and what's the right way to send the array? And if possible, could a double array too be sent?
The clue here is the claim in the question is that sizeof(coords), a 4-element int array, results in 8.
This would only be the case, of course, if on this implementation sizeof(int) is 2. I suppose 16-bit platforms are not entirely unheard of these days, especially in embedded space. But then afterwards, a claim is made that printing an int also results in 4196592, which cannot be the case with a two-byte int, of course.
The only explanation is that the example given here leaves out key information. The code that calls sendfrom() does not access the coords array directly. Most likely .the coords array gets passed as a parameter to this function. Which, of course, turns it into an int *, with its sizeof being 8, resulting in just the first two four-byte int values being send across the socket. This is also an explanation of the compiler warning.
Who knows what happens on the receive side.

Losing data consistently over sockets (but not when using localhost connections)

I'm trying to get comfortable with socket programming. I've written a client/server game, and am seeing some strange results.
Below is the code for the client portion:
while(1){
char response[100];
memset(&buf[0], 0, sizeof(buf));
//buf[numbytes] = '\0';
socklen_t addr_len = sizeof their_addr;
if ((numbytes = recvfrom(sockfd, buf, MAXDATASIZE-1, 0, (struct sockaddr *)&their_addr, &addr_len)) == -1) {
perror("recv");
exit(1);
}
if (strcmp(buf, "exit 99") == 0){
close(sockfd);
return 0;
}
printf("%s\n",buf);
std::cin >> response;
struct msgstruct message;
message.send_data = response;
message.length = strlen(message.send_data);
int n = sendto(sockfd, response, strlen(response), 0, p->ai_addr, p->ai_addrlen);
}
This communicates through the "server", via the following code snippet:
int StartMasterMind(int client, sockaddr_storage addr_in)
{
struct sockaddr_storage their_addr = addr_in;
socklen_t addr_len;
char buf[MAXDATASIZE];
buf[MAXDATASIZE] = '\0';
sendMsg(client, "Welcome to ... M-A-S-T-E-R-M-I-N-D.\nThe game has begun.\n");
// [..] redacted for clarity
for (int i = 0; i < 8; ++i) {
sendMsg(client, "Please enter your guess: ");
addr_len = sizeof their_addr;
recv(client, buf, MAXDATASIZE-1, 0/*, (struct sockaddr *)&their_addr, &addr_len*/);
current_try = GetInputAsColorMap(buf);
// [..] redacted for clarity -- several for() loops below here
}
//basic message structure
struct msgstruct {
int length;
char* send_data;
};
//basic method for sending messages
int sendMsg(int client, char* theMsg)
{
msgstruct message;
message.send_data = theMsg;
message.length = strlen(message.send_data);
return (send(client, message.send_data, message.length, 0));
}
So, if I connect via local host: ./client localhost <port>, then everything appears to be ok:
c#ub1:~/Documents/dev$ ./client localhost 9990
client: connecting to 127.0.0.1
Welcome to ... M-A-S-T-E-R-M-I-N-D.
The game has begun.
Please enter your guess:
However, when connecting over the network from another VM, I consistently get:
c#ub1:~/Documents/dev$ ./client 192.168.1.111 9990
client: connecting to 192.168.1.111
Welcome to ... M-A-S-T-E-R-M-I-N-D.
The game has begun.
Notice the missing Please enter your guess: - I'm a bit at a loss for what to do here. I can't figure out why/when/where this data is getting dropped. Because of this, I'm a little afraid to continue, because I just assume somewhere I have a buffer that's going to overflow and wreck everything.
You're making all the usual mistakes. You're assuming that one send equals one receive. You're not making use of the read count returned by recv() when using he receive buffer. You're assuming that TCP is a messaging protocol. It's a byte-stream protocol.

C++ sockets sending structures

I can send/receive data over sockets using a char array but can't figure out a way to send structures . I found a lot of articles but they are to hard to understand .. As far as I know we have to use a function called snprintf to make packets of data and then some other to revive it . Please I am looking for a very reliable but simple way of data transfer .. Here is some code I wrote to send via char array
int main()
{
int listenfd = 0, connfd = 0;
struct sockaddr_in serv_addr;
char sendBuff[1025];
time_t ticks;
printf("\n\n...Server is starting up...\n\n");
listenfd = socket(AF_INET, SOCK_STREAM, 0);
memset(&serv_addr, '0', sizeof(serv_addr));
memset(sendBuff, '0', sizeof(sendBuff));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(4567);
bind(listenfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
printf("Bind successful\n");
listen(listenfd, 10);
printf("Ready: Waiting for clients\n");
while(1)
{
connfd = accept(listenfd, (struct sockaddr*)NULL, NULL);
ticks = time(NULL);
snprintf(sendBuff, sizeof(sendBuff), "%.24s\r\n", ctime(&ticks));
write(connfd, sendBuff, strlen(sendBuff));
close(connfd);
sleep(1);
}
Client
int main(int argc, char *argv[])
{
int sockfd = 0 /*Socket Descriptor*/, n = 0;
char recvBuff[1024];
struct sockaddr_in serv_addr;
if(argc != 2) {
printf("\n Usage: %s <ip of server> \n",argv[0]);
return 1;
}
memset(recvBuff, '0',sizeof(recvBuff));
if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
printf("\n Error : Could not create socket \n");
return 1;
}
memset(&serv_addr, '0', sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(4567);
if(inet_pton(AF_INET, argv[1], &serv_addr.sin_addr)<=0) {
printf("\n inet_pton error occured\n");
return 1;
}
if( connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
printf("\n Error : Connect Failed \n");
return 1;
}
while ( (n = read(sockfd, recvBuff, sizeof(recvBuff)-1)) > 0) {
recvBuff[n] = 0;
if(fputs(recvBuff, stdout) == EOF) {
printf("\n Error : Fputs error\n");
}
}
if(n < 0) {
printf("\n Read error \n");
}
return 0;
}
For sending structures, in summary: don't. As in, don't attempt to take a structure pointer, the sizeof operator, and a socket send() and expect things will all work out fine, because even if it looks like it works, its already broken in design.
Rather, your structure members should be laid out in a well-defined byte-format that is understood and managed on both ends of the socket connection by common code that is portable. This format (e.g. the protocol) should have portable routines for both assembling your structure into a byte array, and disassembling it out of one. Using these routines on both the client and server side, accounting for sizes, endianness of numeric values, etc, is ultimately the only way to to this both (a) right, and (b) portable.
There are generic solutions available (such as boost::serialization), but ultimately there is no silver bullet. So consider all options and go with the most portable, simplest approach you can.
You can also use this approach.
Use google protocol buffer. A quick link on how to do that is mentioned here
You can make ur own messages and then transmit these messages over sockets udp/tcp.
Another option would be to use an application that does code generation based on a interface description language (IDL). Two excellent options are Apache Thrift and Google protocol buffers.

Not able to receive or send entire packet in socket programming using C

I've been trying to send a packet from a client to a server via sockets. With the help of some of the tips I have made quite bit of progress in my code. However, the server only receives eight bytes from the client and prints them on the console whereas at my client side, It seems that it has sent everything.
Now I am not sure whether the problem is at the sending side or the receiving side. My hunch is that something is wrong at my client side. Could someone please help in verifying my assumption?
Client code:
int main(int argc, char *argv[])
{
int sockfd, portno, n;
struct sockaddr_in serv_addr;
struct hostent *server;
data_struct client_data;
struct packet
{
long int srcID;
long int destID;
int pver;
int profiles;
int 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[256];
struct packet *pkt = (struct packet *) buffer;
char *payload = buffer + sizeof(struct packet);
long double packet_size;
printf("Started Creating packet\n");
pkt->srcID = 01;
pkt->destID = 02;
pkt->pver = 03;
pkt->profiles = 01;
pkt->length = 16;
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 code:
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;
int Pver;
int Profiles;
long int Data;
int Length;
char bytes_to_receive;
int received_bytes;
struct packet
{
long int srcID;
long int destID;
int pver;
int profiles;
int 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[256];
struct packet *pkt = (struct packet *) buffer;
char *payload = buffer + sizeof(struct packet);
long double packet_size;
bytes_to_receive = sizeof(packet_size);
received_bytes = 0;
int rc =0;
while ((rc = recv(newsockfd,pkt,sizeof(packet_size),0)) > 0)
{
received_bytes+=rc;
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: %ld\n", SrcID);
printf("Destination ID: %ld\n", DestID);
printf("profile Version: %d\n", Pver);
printf("No of Profiles: %d\n", Profiles);
printf("Length: %d\n", Length);
printf("data : %ld\n", Data);
}
if (rc == 0)
{
printf("Connection closed by Server\n");
printf("Bytes received: %d\n",received_bytes);
}
if (rc == -1)
{
perror("recv");
}
{
if (close(newsockfd) == -1) {
error("Error closing connection with client 1");
}
printf("Connection with client 1 has been closed\n");
}
return 0;
}
The output that I see on the client's console is:
Client Side: Client 1 trying to connect with server host 130.191.166.230 on port 1234
SUCCESS !!! Connection established
Started Creating packet
packet send done
and on the server's console I see:
Server Side: Data Received from Client_1 are :
Source ID: 1
Destination ID: 2
profile Version: 0
No of Profiles: 1074462536
Length: 0
data : 0
Connection closed by Server
Bytes received: 8
Connection with client 1 has been closed
First of all
recv(newsockfd,pkt,sizeof(packet_size),0)) /* What is packet_size ? */
recv(newsockfd,pkt,sizeof(struct packet),0)) /* You probably mean this. */
That might solve your problems, but there are a few issues with the way you are using TCP sockets.
But at my client side, it prints that it has sent everything
Where ? I don't see you actually checking the number of bytes sent. send(2) can return after sending less that you asked it to.
It shows me that only 8 bytes were sent by Client and prints them out.
TCP is a stream-oriented protocol. You send bytes and they arrive, in the same order. So when you recv(2) something, you might get less (or more than you wrote). So, the following can be true:
client:
send 100 bytes
send 400 bytes
server:
recv 50 bytes
recv 150 bytes
recv 250 bytes
recv 50 bytes
The number of send and recv calls need not be identical when using TCP.
When you call send the function returns the number of bytes actually sent and this number can be less than the number of bytes you wanted to send. So every time you want to send something there must be a loop like the following
bool sendBuffer(SOCKET s, unsigned char *buf, int size)
{
while (size > 0)
{
int sz = send(s, buf, size,0);
if (sz < 0) return false; // Failure
size -= sz; // Decrement number of bytes to send
buf += sz; // Advance read pointer
}
return true; // All buffer has been sent
}
and a similar loop must be done when receiving (in other words recv can return less bytes than what you are asking for).
If you don't make these loops the risk is that everything apparently will work anyway (until the size of an ethernet packet) when you work on your local machine or even over a LAN, but things will not work when working across the internet.
Note also that as other answers pointed out you asked to send sizeof(packet_size) i.e. the number of bytes required to store that variable, not the size of the structure.
There is an informal rule that nobody is allowed to write any software that uses TCP until they memorize this sentence and can fully explain what it means: "TCP is a byte-stream protocol that does not preserve application message boundaries."
What that means is that TCP only ensures that you get out the same bytes you put in and in the same order. It does not "glue" the bytes together in any way.
Before you write any code that uses TCP, you should either use a protocol that is already designed (such as IMAP or HTTP) or design one yourself. If you design one yourself, you should write out a protocol specification. It should specifically define what a protocol-level message will consist of at the byte level. It should specifically state how the receiver finds the ends of messages, and so on.
This may seem a little silly for simple applications, but trust me, it will pay off massively. Otherwise, it's almost impossible to figure out why things aren't work because if the server and client don't quite get along, there's no arbiter to say what's right.
I don't specialise in socket programming but there are a few things I've noticed. As far as I'm aware, I don't think you can send structs over sockets that easily. You may wish to consider a different method.
NB, when using send/recv you're also determing the sizeof packet_size, and not the sizeof the struct.
Googling brought up this about sending structs over sockets: http://ubuntuforums.org/showthread.php?t=613906