I'm very new to socket and TCP, I'm trying to send an array of Int to the server, do some sorting and calculating, then send back the result to the client and repeat.
I tried a few different ways, I either got the result after I close the client or got into a infinite loop.
What is the proper way to keep reading from the client until the client hit EOF?
Here is my server code.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
int main(int argc, char const *argv[]) {
struct sockaddr_in server, client;
int sock, csock, readSize, addressSize;
char buf[256];
bzero(&server, sizeof(server));
server.sin_family = PF_INET;
server.sin_addr.s_addr = inet_addr("127.0.0.1");
server.sin_port = htons(5999);
sock = socket(PF_INET, SOCK_STREAM, 0);
bind(sock, (struct sockaddr*)&server, sizeof(server));
listen(sock, 5);
addressSize = sizeof(client);
csock = accept(sock, (struct sockaddr *)&client, &addressSize);
int values[5];
while (read(csock, values, sizeof(values))) {
// Some sorting and calculating here
for (int i = 0; i < 5; i++) {
printf("%d ", values[i]);
}
}
close(sock);
return 0;
}
And here is my client code.
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
int main(int argc, char const *argv[]) {
struct sockaddr_in server;
char buf[256];
int sock;
bzero(&server, sizeof(server));
server.sin_family = PF_INET;
server.sin_addr.s_addr = inet_addr("127.0.0.1");
server.sin_port = htons(5999);
sock = socket(PF_INET, SOCK_STREAM, 0);
connect(sock, (struct sockaddr *)&server, sizeof(server));
while (1) {
int values[5] = {0};
for (int i = 0; i < 5; i++)
scanf("%d", &values[i]);
write(sock, values, sizeof(values));
}
return 0;
}
Thanks for your help!
On Linux, I observed that if client is terminated with Ctrl-C, then server exits when read()
returns 0 to signify EOF
. If client is given a Ctrl-D, the stream's error state is set and this and all future scanf calls fail without setting values
. This means values
retain their zero initialization, which is sent to server in each iteration of the infinite loop.
Per @user207421, recv()
which I guess how read()
is implemented may return on error on windows to signify and errors. In this case, server would loop with the original code.
In either case, I added error checking for most of calsl (you should also add it for inet_addr()
), and the server will terminate if read()
returns either -1 or 0:
server:
#include <arpa/inet.h>
#include <errno.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <sys/socket.h>
#include <unistd.h>
int main(int argc, char const *argv[]) {
struct sockaddr_in server, client;
int sock, csock;
socklen_t addressSize;
bzero(&server, sizeof(server));
server.sin_family = PF_INET;
server.sin_addr.s_addr = inet_addr("127.0.0.1");
server.sin_port = htons(5999);
sock = socket(PF_INET, SOCK_STREAM, 0);
if(sock == -1) {
printf("socket: %s\n", strerror(errno));
return 1;
}
if(bind(sock, (struct sockaddr*)&server, sizeof(server)) == -1) {
printf("bind: %s\n", strerror(errno));
return 1;
}
if(listen(sock, 5) == -1) {
printf("listen: %s\n", strerror(errno));
return 1;
}
addressSize = sizeof(client);
csock = accept(sock, (struct sockaddr *)&client, &addressSize);
if(csock == -1) {
printf("listen: %s\n", strerror(errno));
return 1;
}
int values[5];
ssize_t n;
while ((n = read(csock, values, sizeof(values)))) {
printf("read %zd\n", n);
if(n <= 0) break;
for (int i = 0; i < n / sizeof(*values); i++) {
printf("%d ", values[i]);
}
printf("\n");
}
close(sock);
return 0;
}
and client:
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <errno.h>
int main(int argc, char const *argv[]) {
struct sockaddr_in server;
char buf[256];
int sock;
bzero(&server, sizeof(server));
server.sin_family = PF_INET;
server.sin_addr.s_addr = inet_addr("127.0.0.1");
server.sin_port = htons(5999);
sock = socket(PF_INET, SOCK_STREAM, 0);
if(sock == -1) {
printf("socket: %s\n", strerror(errno));
return 1;
}
if(connect(sock, (struct sockaddr *)&server, sizeof(server)) == -1) {
printf("connect: %s\n", strerror(errno));
return 1;
}
while (1) {
int values[5] = {0};
for (int i = 0; i < 5; i++) {
int r = scanf("%d", &values[i]);
if(r == EOF) {
return 0;
}
}
ssize_t n = write(sock, values, sizeof(values));
if(n == -1) {
printf("write: %s\n", strerror(errno));
return 1;
}
printf("wrote %zd\n", n);
}
return 0;
}
and here is the output from the server:
$ ./server
read 20 bytes
1 2 3 4 5
and the client (note; client doesn't send partial data):
$ ./client
1
2
3
4
5
wrote 20
1