I have created two programs, a client and a server. They communicate via sockets sending char
arrays of a fixed size of 115 bytes.
The data I want to transfer is stored in the following struct
:
typedef struct {
char origin[14];
char type;
char data[100];
} socket_data;
But in order to send the data serialized, I want to send that information in a single string concatenating al the fields in the struct
so I send a 115 bytes string. If any of those fields does not reach it's max size, I will manually fill the extra array positions with
.
I have created two functions implemented in both client and server that send data through the socket or receive data from the socket.
The two functions are the following:
void socket_send(int socket, char *origin, char type, char *data) {
char info[115]; //data to be sent
socket_data aux;
strcpy(aux.origin, origin);
aux.type = type;
strcpy(aux.data, data);
//Filling up the remaining positions of origin and data variables
for (int i = (int) strlen(aux.origin); i<14; i++) aux.origin[i] = '';
for (int i = (int) strlen(aux.data); i<100; i++) aux.data[i] = '';
//Building up the 115 byte string I want to send via socket
for (int i=0; i<14; i++) info[i] = aux.origin[i];
info[14] = type;
for (int i=0; i<100; i++) info[i+15] = aux.data[i];
ssize_t total_bytes = 115;
ssize_t bytes_written = 0;
//Here I send all the bytes through the socket
do {
bytes_written = write(socket, info + (115 - total_bytes), total_bytes);
total_bytes -= bytes_written;
} while (total_bytes > 0);
}
socket_data socket_rcv(int socket) {
socket_data info;
char sequence[115];
ssize_t total_bytes = 115;
ssize_t bytes_read = 0;
//Here I receive all the bytes from the socket (till I fill up the 115 byte string called sequence)
do {
bytes_read = read(socket, sequence + (115 - total_bytes), total_bytes);
total_bytes -= bytes_read;
} while (total_bytes > 0);
//Then I return a stuct
for (int i=0; i<14; i++) info.origin[i] = sequence[i];
info.type = sequence[14];
for (int i=0; i<100; i++) info.data[i] = sequence[i+15];
return info;
}
As you can see, I loop both read()
and write()
to make sure all bytes are sent as I'm aware sometimes those functions read or write less bytes than demanded.
The issue is that, testing the functionality of the program, I have seen that in the case that less bytes are read (it loops), the program blocks (maybe waiting for another write()
from the server side) instead of reading the remaining bytes in the socket buffer (because all 115 bytes where sent and only 111 received, so there should be still 4 bytes in the socket buffer). Sometimes also, instead of blocking waiting for a possible write()
, the program terminates when it shouldn't...
I can't find the issue here and I'd appreciate some help
EDIT
I created this functions to set up the sockets...
Server:
int socketConfig (connection_info cinfo) {
int socketfd = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (socketfd < 0) {
write(1, "Socket error
", strlen("Socket error
"));
return -1;
}
struct sockaddr_in s_addr;
memset (&s_addr, 0, sizeof (s_addr));
s_addr.sin_family = AF_INET;
s_addr.sin_port = htons(cinfo.port);
s_addr.sin_addr.s_addr = INADDR_ANY;
if (bind (socketfd, (void *) &s_addr, sizeof (s_addr)) < 0) {
write(1, "Bind error
", strlen("Bind error
"));
return -1;
}
listen(socketfd, 3);
return socketfd;
}
int receiveClient(int serverfd) {
struct sockaddr_in client;
socklen_t len = sizeof(client);
return accept(serverfd, (void *) &client, &len);
}
Client:
int connect_to_server(Config config) {
struct sockaddr_in client;
int sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
write(1, "Connecting Jack...
", strlen("Connecting Jack...
"));
if (sockfd < 0) {
write(1, "Error creating the socket
", strlen("Error creating the socket
"));
return -1;
}
memset(&client, 0, sizeof(client));
client.sin_family = AF_INET;
client.sin_port = htons(config.port_jack);
if (inet_aton(config.ip_jack, &client.sin_addr) == 0) {
write(1, "Invalid IP address
", strlen("Invalid IP address
"));
return -1;
}
if (connect(sockfd, (void *) &client, sizeof(client)) < 0) {
write(1, "Error connecting to Jack
", strlen("Error connecting to Jack
"));
return -1;
}
return sockfd;
}
I can guarantee the connection works