I have the following C code for a TCP client:
#define PORT 8888
void connexion(int sock)
{
fd_set rfds;
struct timeval tv;
int retval;
FD_ZERO(&rfds);
FD_SET(0, &rfds);
FD_SET(sock, &rfds);
char buf[512];
retval = select(3, &rfds, NULL, NULL, NULL);
if (retval == -1)
perror("select()");
else if (retval) {
read(retval, buf, 512);
printf("\nbuf: %s", buf);
memset(buf, 0, 512);
}
connexion(sock);
}
int main(int argc, char const *argv[])
{
int sock = 0, valread;
struct sockaddr_in serv_addr;
char *hello = "Hello from client";
char buffer[1024] = {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(PORT);
if(inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr)<=0)
{
printf("\nInvalid address/ Address not supported \n");
return -1;
}
if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
{
printf("\nConnection Failed \n");
return -1;
}
connexion(sock);
}
I try to read the standard input without stopping reading sockets. Indeed, I need to be able to receive messages while I write one. To do this, I use the select function. But I only receive messages from my terminal, never from the server.
The server has nevertheless received the sockets from the client... What is wrong with this code?
you do not use select
in the right way, replace
retval = select(3, &rfds, NULL, NULL, NULL);
by
retval = select(sock+1, &rfds, NULL, NULL, NULL);
select() working for STDIN ...
that works for stdin because stdin is 1 so is less than 3
Out of that in
read(retval, buf, 512);
does not do what you expect, do
if (FD_ISSET(sock, &rfds)) {
read(sock, buf, 512);
printf("buf from socket: %s\n", buf);
}
if (FD_ISSET(stdin, &rfds)) {
read(stdin, buf, 512);
printf("buf from stdin: %s\n", buf);
}
warning if you read on the socket and the null character is not sent/read because printf
will have an undefined behavior, may be save the read length to add the null character at the end
if the socket is closed or you reach the EOF on stdin
both read
may read nothing, so it is better to check their result
Do not use an else
between the two if
because you can have input from both
Your terminal recursion can be replaced by a loop
In your printf
it is strange to produce the newline before and not after, doing after flushes the output
In main
char *hello = "Hello from client"; char buffer[1024] = {0};
are unused