i am haveing trouble transferring int array over socket in c.
what is the correct use of htonl()?
lets say i have :
int arra[3]={6000,7000,8000};
and socket called new_socket
how do i transfer it correctly to the other end of socket?
client is reading it by the following code:
char buf[BUFLEN] = ""; // buffer for recv() calls
for (i = 0; i < nbytes; i += INTLEN) {
int file_port = ntohl(*(int *)&buf[i]);
int i, wp1, ret;
for (i = 0; i < 3; i++) {
wp1 = htonl(arr[i]);
ret = write(sockfd, wp1, sizeof(int));
//error check based on ret
}
this works. TCP is a stream, one write or multiple writes doesn't matter, you can read it all in one go or read until you have necessary number of bytes and do paste the entire program in either side and the output you are getting
Related
I'm trying to send a jpg image from a client process to a server via sockets. The image contains binary data so I want to do it on a low-level programming basis using reads and writes. I'm also sending the image data in iterations of 100 bytes.
This is the code I've done, which is not sending the image identically as I want:
CLIENT
void send_image(char *path, char *filename, int socket) {
int fd = open(path, O_RDONLY); //I open the file of the image.jpg
int n = 1;
while (n > 0) {
char img_data[100];
n = read(fd, img_data, 100); //sending 100 bytes of image each iteration till n=0 (end of file)
if (!n) break;
int sending = 1;
write(socket, &sending, sizeof(int)); //Tell the client the image still has data to send
write(socket, img_data, strlen(img_data));
usleep(250);
}
sending = 0; //Tell the server the image has been fully sent
write(socket, &sending, sizeof(int));
close(fd);
}
SERVER
void receiving_image(char *path) {
int receiving = 0;
int j=0;
char *image_data = NULL; //Variable to store all the image data
read(socket, &receiving, sizeof(int)); //Reads that the client is going to send an image
while (receiving) {
char data[100]; //Variable that stores partial data (100 bytes) of an image on each iteration
read(socket, data, 100);
image_data = realloc(image_data, (j + strlen(data)) * sizeof(char)); //Readjust the size of the main image data.
for (int i=0; i<(int) strlen(data); i++) {
image_data[j] = data[i]; //copy the partial data of the image to the main variable of the image
j++;
}
j = (int) strlen(image_data);
read(socket, &receiving, sizeof(int)); //Read if the image is still sending
}
image_to_directory(path, image_data); //Copy image to directory
}
This compiles and runs fine, but when I check the directory on the server side where the image has been stored, I can see it's not the same image as the client has sent (I confirmed via md5sum and hashes are not equal).
Is there something I am missing?
You shouldn't be using strlen for your binary data length calculations. It is intended only for terminated strings (thus the name). You also have highly-ill-advised naked calls to read/write, which is a recipe for disaster when sending data over sockets.
You never seem to be sending more than 100 bytes at a time, which is helpful in this case to develop a more solid protocol. Consider this:
First octet is a uint8_t byte count N, and will be in 0..100.
Following the byte count, N bytes are transferred.
Repeat 1-2 until no more bytes remain.
Notify the server of EOF by sending a single zero-octet
An example of this sender code is shown here.
void send_image(const char *path, int socket)
{
int fd = open(path, O_RDONLY); //I open the file of the image.jpg
if (fd == -1)
return;
ssize_t n = 0;
do
{
// note the first octet will prefix the length
uint8_t img_data[101];
n = read(fd, img_data+1, 100);
if (n > 0)
{
// you never know just how many bytes are going to
// be sent, so setup the frame, but then ensure even
// piecewise deliver can succeed.
img_data[0] = (uint8_t)n;
ssize_t sent = 0;
size_t pos = 0;
do
{
sent = write(socket, img_data+pos, (n+1)-pos);
if (sent < 0)
break;
pos += sent;
} while ( pos < (n+1) && sent > 0);
}
} while (n > 0);
uint8_t done = 0;
write(socket, &done, sizeof done); // not much we can do if this fails
close(fd);
}
I make no claims the above code will even compile, but the concept should be fairly obvious. That's it, however. Obviously there is more that could/should be done (checksums, restart options, etc.), but that's the basic premise.
The server side can do something similar, which I leave as an exercise for you. The point of all of this is to utilize the return values from your read/write calls. They're there for a reason. If you find yourself coding a "naked" read or write (where you don't gather the result of function and utilize it in some way), chances are you've done something horribly wrong.
I have a problem with receiving the correct values on the server-side of my client-server program.
header file included in both server and client:
#define CHUNK_SIZE 1024
#define ARR_LEN 3
client:
int uids[ARR_LEN] = {1994, 2423, 1222};
unsigned int uidlen = 0;
char uidbuffer[CHUNK_SIZE] = {0};
for(int i = 0; i < ARLL; i++)
{
uidlen = strlen(uids[i])+1;
snprintf(uidbuffer, uidlen, "%s", uids[i]);
if(send(socket, uidbuffer, strlen(uidbuffer), 0) < 0)
DIE("Write Error");
if(recv(socket, uidbuffer, sizeof(uidbuffer), 0) < 0)
DIE("Acknowledge Error");
memset(uidbuffer, 0, sizeof(uidbuffer));
}
server:
char uid_buff[CHUNK_SIZE];
for(int i = 0; i < ARR_LEN; i++)
{
memset(uid_buff, 0, sizeof(uid_buff));
// receiving the UID and storing it directly
if(recv(client_sock, uid_buff, sizeof(uid_buff), 0) < 0)
DIE("Receive Error");
printf("buffer content: %s\n", uid_buff);
uid_str = uid_buff;
uids[i] = (uid_t)strtol(uid_str, (char **)NULL, 10);
if(send(client_sock, uid_buff, sizeof(uid_buff), 0) < 0)
DIE("Acknowledge Error");
}
These are only parts of my program. I tried to only include the relevant parts. The output is this:
buffer content: 1994
buffer content: 24231222
buffer content:
While I want it to be:
buffer content: 1994
buffer content: 2423
buffer content: 1222
What could be the problem? I know that it's not so easy and that server–client communication is carried out in a stream of bytes rather than messages, but I want to mimmic that functionality by acknowledging every received "message". Could you please clue me what to do? I'm getting desperate.
You will need a protocol.
For example, you define that each message in your application has following format:
xx | message
this means first two bytes (mind the endianness) you receive indicate the length of the message that follows. Now you should first receive first two bytes - check the length - and then receive exactly that number of bytes. After that you know you have successfully received that message. And then you can proceed to other messages (which could/should have similar format: length + message itself).
Example:
Say you want to send three messages:
char s1[]="message1";
char s2[]="message2";
char s3[]="message3";
//You do this(client side):
int x1 = strlen(s1); // length of message1
int intsize = 4; // just size of integer -we'll need in next call
sendall(socket, &x1, &intsize); // send length of first message
sendall(socket, s1, &x1); // Now send the message
//On server:
int x = 0;
int y = 4; //size of integer most probably
receiveall(socket,&x,&y);//get length first; y=4 because that is size of integer
receiveall(socket, buffer, &x); // now we know how many bytes to expect - x - so request that number of bytes only
you can repeat this logic for other messages too.
Finally, you want to use such functions (here) instead of send and receive (because send and receive might not send/receive the number of bytes you tell it to):
int sendall(int s, char *buf, int *len)
{
int total = 0; // how many bytes we've sent
int bytesleft = *len; // how many we have left to send
int n;
while(total < *len) {
n = send(s, buf+total, bytesleft, 0);
if (n == -1) { break; }
total += n;
bytesleft -= n;
}
*len = total; // return number actually sent here
return n==-1?-1:0; // return -1 on failure, 0 on success
}
you will need a similar receiveall function.
You do not show the code that establishes the connection.
If you are using UDP sockets, each message is stand alone, you will receive a separate message for each message sent, but not necessarily in the same order.
If you are using TCP or Unix sockets, data may be received in chunks of different sizes than those used for sending. Only the sequence of bytes is preserved, not the chunk sizes. You need to specify a protocol: unless you specify a fixed number of bytes per message, you need to send some sort of separator to allow the server to tell where each message ends.
I am a new C programmer and so you will have to excuse my lack of knowledge. I am trying to use sockets in C on a windows machine to send data back and forth between a client and server. I am using the tools of cygwin with the codeblocks IDE. Simple send and receives were not working and so after some searching I was under the impression my problem was I needed a send_all and recv_all function. I have written the following two functions but receive seems to always get stuck in an infinite loop. I am not really sure why.
void send_all(int socket, void *buffer, int length) {
size_t i = 0;
for (i = 0; i < length; i += send(socket, buffer, length - i, 0)){
printf("Completed: %d bytes \r", i);
}
printf("Send Completed: %d bytes \n", length);
}
void recv_all(int sockfd, void *buffer, int length){
size_t i = 0;
for (i = 0; i < length; i+= recv(sockfd, buffer + i, length - i, 0)){
printf("Completed: %d bytes \r", i);
}
printf("Receive Completed: %d bytes \n", length);
}
I am wondering if it is because the receive doesn't know how many bytes the send is sending it. All advice is appreciated but please keep it constructive. Thanks.
recv() actually returns a signed value (int in Winsock, ssize_t in POSIX). Its return value can be a negative number if a read error occurred, OR if the socket is in non-blocking mode and no data is available. Its return value is zero if the socket was closed gracefully (this would cause an infinite loop in your code).
You will need to check the return value before you add it to your byte counter, to detect both of these conditions.
If your socket is in blocking mode (the default), your code will block indefinitely until the required amount of data has been received, or an error occurs (once you add code to check for that). Given the name of your function this seems to be the behavior you want. If so, your general approach is sound.
ssize_t bytesRead = 0;
while (bytesRead < length)
{
ssize_t rv = recv(/* ... */);
if (rv == 0)
{
printf("Socket closed gracefully before enough data received\n");
break;
}
else if (rv < 0)
{
// if your socket is non-blocking, check for EAGAIN which
// would mean no data is currently available; in this case you
// could do something like call select() on the socket to
// go to sleep until more data comes in
printf("Read error occurred before enough data received\n");
break;
}
bytesRead += rv;
}
I'm continuously sending arrays of pixel values (160x120) as a bytestream from LabVIEW to a C-program through TCP/IP. Then I'm converting the bytes to uint32 values and printing the received data in the console application. The goal here, is that I want to divide the received data in 1D arrays, so every 1D array will consists of (160x120=19200) integer values, so it represents a frame. In better words, the array has to collect every 19200 integers of the received data and display them in the console application. Then the same array has to collect the next 19200 integers and display them in the console application and so on. I appreciate if anyone shows how to do it.
WSADATA wsa;
SOCKET s , new_socket;
struct sockaddr_in server , client;
int c;
int iResult;
char recvbuf[DEFAULT_BUFLEN];
int recvbuflen = DEFAULT_BUFLEN;
typedef unsigned int uint32_t;
unsigned int i;
size_t len;
uint32_t* p;
uint32_t value;
p = (uint32_t*)((void*)recvbuf);
do
{
iResult = recv(new_socket, recvbuf, recvbuflen, 0);
len = iResult/sizeof(uint32_t);
for(i=0; i < len; i++)
{
value = p[i];
}
printf("%d\n", value);
}
while ( iResult > 0 );
closesocket(new_socket);
WSACleanup();
return 0;
This code is making lots of assumptions about the sizes and alignment of things. On x86 systems this will work fine, but beware systems that require alignment. It is also assuming that both systems have the same endien-ness.
To receive data chunked into 160x120 uint32_t byte chunks (assuming your DEFAULT_BUFLEN is correct):
int receivedCount = 0;
do
{
iResult = recv( new_socket,
&recvbuf[receivedCount],
DEFAULT_BUFLEN-receivedCount,
0 );
if ( iResult == 0 ) break; //0 == socket closed
receivedCount += iResult;
if ( receivedCount < DEFAULT_BUFLEN )
continue; //still receiving full frame
for(int i=0; i<160*120; i++)
printf("%d\n",(unsigned int)p[i]);
receivedCount = 0;
}
while( wantToContinueCapturingFrames );
This will continuously wait for data until a full frame has been received. Once a full frame has been received it will print out the data from the frame. If the remote system closes the connection this will exit without printing any partial frame.
This isn't really sufficient for "real" applications since it is blocking in recv waiting for data. There's no provision to (gracefully) abort without the remote system either sending data or closing the connection, but fixing that isn't really what you are asking about here.
I currently have a client app that works but it is single threaded.
my packets look like this: < len_of_data>|< data>"
"|" is used as a separator for my data.
< len_of_data> is always 4 digits long followed.
< data> looks like: |< transaction id>|< command>|< buflen>|< buf>|< checksum>|
my code to create the packets is:
_snprintf_s(data_buffer, WS_MAX_DATA_PACKET_SIZE,
WS_MAX_DATA_PACKET_SIZE - 1,
"%s%d%s%d%s%d%s%s%s%d%s",
WS_PACKET_SEP, pkt->transaction_id,
WS_PACKET_SEP, pkt->command,
WS_PACKET_SEP, pkt->bufsize,
WS_PACKET_SEP, pkt->buf,
WS_PACKET_SEP, pkt->checksum, WS_PACKET_SEP);
buf_len = strlen(data_buffer);
_snprintf_s(send_buffer, WS_MAX_DATA_PACKET_SIZE,
WS_MAX_DATA_PACKET_SIZE - 1, "%04d%s%s",
buf_len, WS_PACKET_SEP, data_buffer);
buf_len = strlen(send_buffer);
// Send buffer
bytes_sent = send(ConnectSocket, send_buffer, buf_len, 0);
The client thread sends a command to the server, then calls a GetIncomingPackets() function. In GetIncomingPackets(), I call recv() to get 5 bytes, this should be the len of the rest of packet, I parse these 5 bytes and verify that they match my expected format. Then I convert the first 4 bytes to an integer, x. Then I call recv() again to get x bytes more and then parse those out into my packet structure.
The problem happens when I add another thread to do the same thing (send and receive commands).
I start my app and fire 2 threads and send them to send different commands and wait for responses. When the threads call GetIncomingPackets(), the data I am getting back is invalid. The first 5 bytes I am expecting are missing sometimes, and I just get the following 5 bytes, therefore I am unable to get my < len_of_data > packet.
I even added a critical section block between the 2 recv() calls in my GetIncomingPackets() so the treads dont interrupt each other while getting a full packet.
Without some extra code for error checking, this how the function looks like
#define WS_SIZE_OF_LEN_PACKET 5
bool GetIncomingPackets(SOCKET sd, dev_sim_packet_t *pkt )
{
char len_str_buf[WS_SIZE_OF_LEN_PACKET + 1] = {0}; // + 1 for NULL char
char data_buf[WS_MAX_DATA_PACKET_SIZE + 1] = {0};
int ret = 0;
int data_len = 0;
EnterCriticalSection( &recv_critical_section );
nReadBytes = WS_RecvAll(sd, len_str_buf, WS_SIZE_OF_LEN_PACKET );
ret = WS_VerifyLenPacket(len_str_buf);
// Convert data packet lenght string received to int
data_len = WS_ConvertNumberFromString(len_str_buf, WS_SIZE_OF_LEN_PACKET );
// Get data from packet
nReadBytes = WS_RecvAll(sd, data_buf, data_len);
LeaveCriticalSection( &recv_critical_section );
ret = ParseMessager(data_buf, data_len, pkt);
}
My question is, what could be causing this problem, and how could I fix it? Or is there better ways to do what i am trying to do. The reason that I'm trying to make it multi-threaded is because my app will communicate with 2 other sources, and I want to have a thread to handle each request that comes in from either source.
thanks in advance and feel free to ask any questions if I didn't explain something well.
Here's the code for WS_RecvAll(). The buffer is a static buffer declared in GetIncomingPackets() like this:
char data_buf[WS_MAX_DATA_PACKET_SIZE + 1] = {0}; // + 1 for NULL char
int WS_RecvAll(SOCKET socket_handle, char* buffer, int size)
{
int ret = 0;
int read = 0;
int i = 0;
char err_buf[100] = {0};
while(size)
{
ret = recv(socket_handle, &buffer[read], size, 0);
if (ret == SOCKET_ERROR)
{
printf("***ERROR***: recv failed, error = %d\n", WSAGetLastError());
return WS_ERROR_RECV_FAILED;
}
if (ret == 0) {
break;
}
read += ret;
size -= ret;
}
return read;
}
It's very difficult to debug MT problems, particularly at one remove, but if you are using astatic buffer, should not:
LeaveCriticalSection( &recv_critical_section );
ret = ParseMessager(data_buf, data_len, pkt);
be:
ret = ParseMessager(data_buf, data_len, pkt);
LeaveCriticalSection( &recv_critical_section );
And why use a static buffer in any case?
Im curious to know whether you have used the same socked descriptor in both the threads to connect to the server.