I am having difficulty changing the amount of data my server sends and getting it to send data. This code fails, but works when I change the size of buffer
to 16 characters.
This is the code from transferclient.c
#include <errno.h>
#include <getopt.h>
#include <netdb.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#define BUFSIZE 218
int main(int argc, char **argv) {
unsigned short portno = 10823;
int sock = 0;
struct sockaddr_in serv_addr;
char buffer[32] = {0};
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
printf("\n Socket creation error \n");
return -1;
}
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(portno);
printf("Attemping to connect\n");
if (connect(sock, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
{
printf("\nConnection Failed \n");
return -1;
}
printf("Connected\n");
read(sock, buffer, 16);
return 0;
}
This is the code from transferserver.c
#include <errno.h>
#include <getopt.h>
#include <netdb.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#define BUFSIZE 218
int main(int argc, char **argv) {
int portno = 10823; /* port to listen on */
int server_fd, new_socket;
struct sockaddr_in address;
int opt =1;
int addrlen = sizeof(address);
// Creating socket file descriptor
if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0)
{
perror("socket failed");
exit(EXIT_FAILURE);
}
// Attaching the socket to the port
if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)))
{
perror("setsockopt");
exit(EXIT_FAILURE);
}
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(portno);
// Forcefully attaching socket to the port
if (bind(server_fd, (struct sockaddr *) &address, sizeof(address))<0)
{
perror("bind failed");
exit(EXIT_FAILURE);
}
if (listen(server_fd, 3) < 0) {
perror("listen");
exit(EXIT_FAILURE);
}
printf("Listening\n");
while ((new_socket = accept(server_fd, (struct sockaddr *) &address, (socklen_t*) &addrlen)) > 0)
{
printf("%d\n", new_socket);
printf("Socket connected\n");
}
return 0;
}
Server side
Listening
4
Socket connected
***Client Side***
```
Attemping to connect
Connected
When I change the line in transferclient.c to 32 bytes.
char buffer[32] = {0};
The sockets fail to connect.
Server side
Listening
Client Side
Attemping to connect
Why is that?
CodePudding user response:
In the client code, you don't seem to be setting all fields of serv_addr
.
struct sockaddr_in serv_addr;
[...]
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(portno);
Because you are not setting serv_addr.sin_addr
, it will have an indeterminate (garbage) value when you pass it to the function connect
.
My guess is that changing the size of the array caused the sin_addr
field of serv_addr
to have a different initial (garbage) value. That is why the code works when buffer
has a size of 16
but fails when it has a size of 32
.
CodePudding user response:
In my opinion... apart of what has already been mentioned in other answers, you are lacking constants... you should define something like:
#define BUFFER_SIZE (32)
and then use
char buffer[BUFFER_SIZE];
and
read(sock, buffer, BUFFER_SIZE);
or, if you don't like this approach, use this other:
char buffer[32];
and later
read(sock, buffer, sizeof buffer);
but if you put different numbers in the buffer size and in the read()
call it is normal that it doesn't work ok when you call read()
with 16
as the number of characters to read.
By the way, it is common that you ask a socket to read a fixed amount of bytes, and it returns less bytes than the amount you requested, so IT IS VERY IMPORTANT THAT YOU CHECK THE RETURN VALUE OF read(2)
. Something like:
ssize_t n = read(sock, buffer, BUFFER_SIZE);
as from buffer[n]
to buffer[sizeof buffer - 1]
there can be nothing useful to your code (rests of a previous read, or similar) It is quite common to print it with something like:
if (n > 0)
printf("Read: [%.*s]\n", n, buffer);
that will print that number of received valid characters, and not what is behind them in the buffer.