I have a simple tcp based client and server written in c, but once I establish a connection after the server sends a message back to the client, the connection stops working. Could you help me fix this - I would like the server to continue receiving/ sending messages to the client.
Code:
Server.c
#include <stdio.h>
#include <errno.h>
#include <sys/socket.h>
#include <resolv.h>
#include <arpa/inet.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <fcntl.h>
#include <unistd.h>
#define port 5000
#define buf 512
void answer(int);
int main(int argc, char *argv[]){
int sock = socket(AF_INET, SOCK_STREAM, 0);
int portid;
int backlog = 10;
struct sockaddr_in addr;
char BUFF[buf];
int n;
int received = 0;
int connfd;
if(sock == -1){
perror("socket error");
exit(errno);
}
memset(&addr,0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = INADDR_ANY;
if(bind(sock, (struct sockaddr*) &addr, sizeof(addr)) == -1){
perror("bind error");
exit(errno);
}
if(listen(sock, backlog) == -1){
perror("listen error");
exit(errno);
}
listen(sock, 5);
struct sockaddr_in cliaddr;
//struct sockaddr_in addr;
int cliaddr_len = sizeof(cliaddr);
while(1){
connfd = accept(sock, (struct sockaddr*)&cliaddr,&cliaddr_len);
if(connfd == -1){
perror("error connfd");
exit(errno);
}
portid = fork();
if(portid<0)
perror("error on fork");
if(portid ==0){
close(sock);
answer(connfd);
exit(0);
}
//close(sock);
}
close(connfd);
return 0;
//close(sock);
//return 0;
}
void answer(int connfd){
int n;
char BUFF[buf];
memset(BUFF,buf,buf);
n = read(connfd,BUFF,buf);
printf("connected: %s",BUFF);
//received = 1;
//memset(BUFF,0,buf);
printf("please enter your message: ");
memset(BUFF,0,buf);
fgets(BUFF,buf, stdin);
n = write(connfd, BUFF,strlen(BUFF));
if(n<0) err("writing to socket problem");
}
Your server is calling fork, then if(portid ==0){...get and send message...}, then it loops back to the top of the loop where it tries to accept() --- not the job of the child, but the child is trying to do that anyway.
Refactor your code to do what you want. Break it into smaller parts that are simple for you to inspect so you can see things like this.
This is because you recv() data just one time. Use a loop to receive until the client disconnects.
while ((n = read(connfd,BUFF,buf))
{
printf("connected: %s",BUFF);
//received = 1;
//memset(BUFF,0,buf);
printf("please enter your message: ");
memset(BUFF,0,buf);
fgets(BUFF,buf, stdin);
n = write(connfd, BUFF,strlen(BUFF));
if(n<0) err("writing to socket problem");
}
You are reading the data in your child, so once the child is done the program exits, so try to read in the parent and send the data along to the child.
Related
I'm trying to launch multiple servers, at once, in a c program. For the sake of simplicity let's say 5 servers.
If I understand well the sockets, each of them must be listening to a different IP socket address (different PORT, different IP interface address).
I thought to do that inside a loop, incrementing port number by i at each turn. Here's my current code just to launch one server. I know it's possible with bash by launching the same process in background, but in C I really don't know how to do that and if it's even possible
#include <unistd.h>
#include <stdio.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <string.h>
#include <errno.h>
long PORT;
int main(int argc, char const *argv[])
{
/* 1. Open a socket
2. Bind to a address(and port).
3. Listen for incoming connections.
4. Accept connections
5. Read/Send
*/
int listenerSocket; /* socket for accepting connections */
int clientSocket; /* socket connected to client */
struct sockaddr_in server;
struct sockaddr_in client; /* client address information */
char buf[100]; /* buffer for sending & receiving data */
int errnum;
listenerSocket = socket(AF_INET, SOCK_STREAM, 0);
if(listenerSocket == -1){
perror("erreur lors de la création du socket");
}
PORT = strtol(argv[1], NULL, 10);
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port= htons(PORT);
if (bind(listenerSocket, (struct sockaddr *)&server, sizeof(server)) < 0) {
perror("bind failed");
exit(EXIT_FAILURE);
}
puts("Server waiting for connection...");
while(1){
if (listen(listenerSocket, 5) < 0){
perror("listen failed");
exit(EXIT_FAILURE);
}
int c = sizeof(client);
if((clientSocket = accept(listenerSocket, (struct sockaddr*) &client, &c)) < 0){
puts("error accepting the request");
perror("Accept()");
}
puts("connection accepted");
while(1){
if( recv(clientSocket, buf, sizeof(buf), 0) < 0) {
errnum = errno;
perror("Recv()");
printf("val printed by errno: %d\n",errno);
}
printf("Message : %s\n", buf);
}
if (send(clientSocket, buf, sizeof(buf), 0) < 0)
{
perror("Send()");
exit(7);
}
close(clientSocket);
close(listenerSocket);
printf("Server ended successfully\n");
exit(0);
}
I'm writing 2 small test programs in C (client/server) and I'm having trouble sending messages from the server to the client (but the other way around works just fine). The server says it sent 20 bytes, but on the client's end it says "failed to receive data". I would appreciate any help, thank you so much! My code is below:
Server:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <netinet/in.h>
int main(int argc, char* argv[])
{
int sockfd, client_sockfd;
struct sockaddr_in server;
int reading, fileSize;
int i; //counter
int bytesSent;
char test[20] = "test message\n";
memset(&server, 0, sizeof(server));
server.sin_family = AF_INET;
server.sin_port = htons(atoi(argv[1])); //assign port to listen to
server.sin_addr.s_addr = INADDR_ANY; //IP address
if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) //create socket failed
{
perror("socket");
exit(1);
}
if(bind(sockfd, (struct sockaddr *) &server, sizeof(server)) == -1) //connect server socket to specified port
{
perror("bind call failed");
exit(1);
}
//printf("listening to port %d\n", server.sin_port);
if(listen(sockfd, 5) == -1) //queue size of 5
{
perror("listen call failed");
exit(1);
}
while(1) //infinite loop to process connections from clients
{
client_sockfd = accept(sockfd, NULL, NULL); //accept anything
if(client_sockfd == -1)
perror("accept call failed");
bytesSent = send(client_sockfd, test, 20, 0);
printf("bytes sent: %d\n", bytesSent);
}
close(client_sockfd);
close(sockfd);
return 0;
}
Client:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <fcntl.h>
#include <errno.h>
int main(int argc, char* argv[])
{
int sockfd;
struct sockaddr_in server;
struct hostent *server_ip_address;
server_ip_address = gethostbyname("eos-class.engr.oregonstate.edu");
int sent; //number of bytes sent
int received; //number of bytes received
char passedMsg[20]; //holds received message
if(server_ip_address == NULL)
{
fprintf(stderr, "could not resolve server host name\n");
exit(1);
}
memset(&server, 0, sizeof(server));
server.sin_family = AF_INET;
server.sin_port = htons(atoi(argv[3])); //assign port to connect to
memcpy(&server.sin_addr, server_ip_address->h_addr, server_ip_address->h_length);
if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) //create socket failed
{
perror("socket");
exit(1);
}
if(connect(sockfd, (struct sockaddr *) &server, sizeof(server)) == -1) //connect socket to remote address failed
{
printf("tried to connect to port %d\n", server.sin_port);
perror("connect");
exit(1);
}
if((received = recv(sockfd, passedMsg, 20, 0)) < 0);
{
printf("Failed to receive data\n");
exit(1);
}
printf("Received message: %s\n", passedMsg);
close(sockfd);
return 0;
}
In your client code, in the error checking for recv, change printf to perror. If you do, the output will be:
Failed to receive data: Success
So the recv call was successful, but the error code ran anyway. Why? Let's take a closer look at that if statement:
// what's this? ----v
if((received = recv(sockfd, passedMsg, 20, 0)) < 0);
{
printf("Failed to receive data\n");
exit(1);
}
There's a stray ; after the condition in the if statement. This means that the if statement does nothing if the condition is true, and that the following block is not the body of the if but an independent block that always runs.
Get rid of the extra ; and you get the expected results.
I have written a simple echo server and a client in C.
Here is the server code:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <arpa/inet.h>
#include <errno.h>
#include <string.h>
#include <signal.h>
#include "unp.h"
#define SERVER_PORT 10000
void start_echo_service(int connfd);
void SIGCHLD_handler(int signum);
int main()
{
int listenfd, connfd;
socklen_t len;
struct sockaddr_in server_addr, client_addr;
pid_t child_pid;
printf("***Starting the echo server***\n");
if((listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
printf("Failed to create connection socket. Exiting...\n");
exit(0);
}
bzero(&server_addr, sizeof(struct sockaddr_in));
bzero(&client_addr, sizeof(struct sockaddr_in));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
server_addr.sin_port = htons(SERVER_PORT);
if(bind(listenfd, (struct sockaddr *) &server_addr, sizeof(server_addr)) < 0)
{
strerror(errno);
exit(0);
}
if(listen(listenfd, 1000) < 0)
{
strerror(errno);
exit(0);
}
/* Add the handler for SIGCHLD */
struct sigaction sigchld_action;
sigchld_action.sa_handler = SIGCHLD_handler;
sigemptyset(&sigchld_action.sa_mask);
sigchld_action.sa_flags = 0;
if(sigaction(SIGCHLD, &sigchld_action, NULL) < 0)
{
printf("Error while adding handler for SIGCHLD\n");
exit(0);
}
while(1)
{
len = sizeof(client_addr);
if((connfd = accept(listenfd, (struct sockaddr *) &client_addr, &len)) < 0)
{
if(errno == EINTR)
continue;
else
{
strerror(errno);
exit(0);
}
}
child_pid = fork();
if(child_pid < 0)
{
//some error occured
strerror(errno);
exit(0);
}
else if(child_pid == 0)
{
// child process
close(listenfd);
start_echo_service(connfd);
close(connfd);
exit(1);
}
close(connfd);
}
close(connfd);
return 1;
}
void SIGCHLD_handler(int signum)
{
pid_t pid;
if((pid = waitpid(-1, NULL, 0)) > 0)
printf("Harvested child (pid): %d\n", pid);
}
void start_echo_service(int connfd)
{
char buf[256];
int bytes_read;
while(1)
{
if((bytes_read = read(connfd, buf, sizeof(buf))) > 0)
{
writen(connfd, buf, bytes_read);
continue;
}
else if(bytes_read == 0)
break;
else
{
if(errno == EINTR)
continue;
else
{
printf("Read error\n");
break;
}
}
}
}
Here is the client code:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include "unp.h"
#define SERVER_PORT 10000
void start_echo_client(int connfd);
int main(int argc, char *argv[])
{
int connfd;
struct sockaddr_in server_addr;
if(argc != 2)
{
printf("Usage: echo_client <server-address>\n");
exit(-1);
}
bzero(&server_addr, sizeof(server_addr));
server_addr.sin_family = AF_INET;
inet_pton(AF_INET, argv[1], &(server_addr.sin_addr));
server_addr.sin_port = htons(SERVER_PORT);
if((connfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
strerror(errno);
exit(0);
}
if(connect(connfd, (struct sockaddr *) &server_addr, sizeof(server_addr)) < 0)
{
strerror(errno);
exit(0);
}
start_echo_client(connfd);
return 1;
}
void start_echo_client(int connfd)
{
char buffer[256];
while(fgets(buffer, sizeof(buffer), stdin) != NULL)
{
writen(connfd, buffer, strlen(buffer));
readn(connfd, buffer, strlen(buffer));
printf("%s", buffer);
}
}
I start my server with ./echo_server on one shell.
I start my client with ./echo_client 127.0.0.1 on another shell. So far, so good.
On my client, I type a message, say hello. The server echoes it back. Now, I terminate my server with Ctrl+C. The client is still running. Now, I type another message on the client, say zzz. I still get an echo back and zzz is printed on the shell. On typing another message on the client, it terminates.
I guess it may have something to do with the server being in uninterruptible sleep when I terminate it, but I can't be sure.
Here is the link to unp.h and unp.c
start_echo_client prints buffer irrespective of the return from readn, isn't? Even if server closed, buffer would contain contents of what happened with writen ( You use same buffer for write and read). Hence i think, you assume there was an echo from server while it was not.
The test with tcpdump as well indicates that FIN does arrive with ctrl-c on the server terminal. Client tries write ignoring the peer closure for which RST is received.
Also, read didn't yield zero on FIN. I changed to recv then the closure was caught.
Return the number of bytes read in the readn function instead what is being currently done and if its zero, then don't print buffer.
After looking at Beej's guide to network programming, I am trying to redo my server.c using select instead of fork. I am not too sure what is going wrong; my program compiles, but doesn't accept connections. I know that my loop containing i<=fdmax isn't functioning properly, but I can't figure out why. It seems like the if statements are not working appropriately.
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <sys/wait.h>
#include <errno.h>
#include <sys/select.h>
#define Connections 5
void SignalCatcher(int signum)
{
wait3(NULL,WNOHANG, NULL);
//wait(-1);
}
int main(int argc, char**argv)
{
int listenfd,connfd,n, i;
struct sockaddr_in servaddr,cliaddr;
socklen_t clilen;
pid_t childpid;
char mesg[1000];
FILE *inputFile;
inputFile = fopen("movie.txt", "r");
char returnMsg[1000];
int fdmax, newfd;
fd_set readfd;
fd_set mastersocket;
FD_ZERO(&mastersocket);
FD_ZERO(&readfd);
//Creating socket number
listenfd=socket(AF_INET,SOCK_STREAM,0);
//Setting up the internet address
bzero(&servaddr,sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr=htonl(INADDR_ANY);
servaddr.sin_port=htons(32000);
bind(listenfd,(struct sockaddr *)&servaddr,sizeof(servaddr));
//Listening for clients
listen(listenfd,1024);
FD_SET(listenfd, &mastersocket);
fdmax=listenfd;
//signal(SIGCHLD, SIG_IGN);
signal(SIGCHLD, SignalCatcher);
//Infinite loop that waits for/accepts connections.
for(;;)
{
readfd = mastersocket;
clilen=sizeof(cliaddr);
if(select(fdmax+1, &readfd, NULL, NULL, NULL) == -1) {
perror("select");
exit(4);}
//connfd = accept(listenfd,(struct sockaddr *)&cliaddr,&clilen);
for(i=0; i<=fdmax;i++)
{
if (FD_ISSET(i, &readfd)){
if(i==listenfd){
printf("-SUCCESS\n");
clilen = sizeof cliaddr;
connfd = accept(listenfd,(struct sockaddr *)&cliaddr,&clilen); }
if (connfd!=-1)
{
// if ((childpid = fork()) == 0)
// {
close (listenfd);
for(;;)
{
n = recvfrom(connfd,mesg,1000,0,(struct sockaddr *)&cliaddr,&clilen);
if (n == -1 /*&& errno == EWOULDBLOCK*/) continue;
else if(n==0) break;
//sendto(connfd,mesg,n,0,(struct sockaddr *)&cliaddr,sizeof(cliaddr));
//write(connfd , mesg , strlen(mesg)); //both work
//write(connfd , "" , 1);
printf("-------------------------------------------------------\n");
printf("%d",listenfd);
mesg[n] = 0;
printf("Received the following:\n");
printf("%s",mesg);
printf("-------------------------------------------------------\n");
}
// }
close(connfd);
} //if connfd!=-1
}
} //for i<=fdmax
}
}
You can answer this question yourself by examining the functions' return values. In network programming, the usual idiom is something along the lines of:
if (foo() < 0) {
fprintf(stderr, "foo: %s\n", strerror(errno));
/* recover from error or... */
exit(EXIT_FAILURE);
}
...where foo() is one of bind(), listen(), accept(), send*/recv*() and so on.
Go ahead and try. errno will tell you what's wrong.
Besides, it's unclear why you are using select() at all. All you do is listen on a single socket, and you close it as soon as someone connects. Instead, you could just accept(listenfd).
firstly you should not close the listening fd it should be close while exiting the program. secondly we need to accept all incoming connections that are queued up on the listening socket.then if listening socket is not readable then an existing connection must be readable, so read the data for that connection. I just read once but u can read in loop for that connection until recv fails.
following code change should work:
//Infinite loop that waits for/accepts connections.
for(;;)
{
readfd = mastersocket;
clilen=sizeof(cliaddr);
if(select(fdmax+1, &readfd, NULL, NULL, NULL) == -1) {
perror("select");
exit(4);}
//connfd = accept(listenfd,(struct sockaddr *)&cliaddr,&clilen);
for(i=0; i<=fdmax;i++)
{
if (FD_ISSET(i, &readfd)){
if(i==listenfd){
printf("-SUCCESS\n");
clilen = sizeof cliaddr;
connfd = accept(listenfd,(struct sockaddr *)&cliaddr,&clilen);
if (connfd!=-1)
{
FD_SET(connfd, &mastersocket);
if (connfd > fdmax) {
fdmax = connfd;
}
}
}
else
{
n = recvfrom(i,mesg,1000,0,(struct sockaddr *)&cliaddr,&clilen);
if ((n == -1 /*&& errno == EWOULDBLOCK*/) || (n==0)) {
close (i);
FD_CLR (i, &mastersocket);
if (i == fdmax)
{
while (FD_ISSET(fdmax, &mastersocket) == 0)
fdmax -= 1;
}
}
//sendto(i,mesg,n,0,(struct sockaddr *)&cliaddr,sizeof(cliaddr));
//write(i , mesg , strlen(mesg)); //both work
//write(i , "" , 1);
printf("-------------------------------------------------------\n");
printf("%d",listenfd);
mesg[n] = 0;
printf("Received the following:\n");
printf("%s",mesg);
printf("-------------------------------------------------------\n");
}
}
} //for i<=fdmax
}
I tried your code with changes and its working fine to me.
Also if you want only one client communicate with server at a time then enable the while loop for reading client data.
server.c
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <sys/wait.h>
#include <errno.h>
#include <sys/select.h>
#define Connections 5
void SignalCatcher(int signum)
{
wait3(NULL,WNOHANG, NULL);
//wait(-1);
}
int main(int argc, char**argv)
{
int listenfd,connfd,n, i;
struct sockaddr_in servaddr,cliaddr;
socklen_t clilen;
pid_t childpid;
char mesg[1000];
FILE *inputFile;
inputFile = fopen("movie.txt", "r");
char returnMsg[1000];
int fdmax, newfd;
fd_set readfd;
fd_set mastersocket;
FD_ZERO(&mastersocket);
FD_ZERO(&readfd);
//Creating socket number
listenfd=socket(AF_INET,SOCK_STREAM,0);
//Setting up the internet address
bzero(&servaddr,sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr=htonl(INADDR_ANY);
servaddr.sin_port=htons(32000);
bind(listenfd,(struct sockaddr *)&servaddr,sizeof(servaddr));
//Listening for clients
listen(listenfd,1024);
FD_SET(listenfd, &mastersocket);
fdmax=listenfd;
//signal(SIGCHLD, SIG_IGN);
signal(SIGCHLD, SignalCatcher);
//Infinite loop that waits for accepts connections.
for(;;)
{
readfd = mastersocket;
clilen=sizeof(cliaddr);
if(select(fdmax+1, &readfd, NULL, NULL, NULL) == -1) {
perror("select");
exit(4);}
//connfd = accept(listenfd,(struct sockaddr *)&cliaddr,&clilen);
for(i=0; i<=fdmax;i++)
{
if (FD_ISSET(i, &readfd)){
if(i==listenfd){
printf("-SUCCESS\n");
clilen = sizeof cliaddr;
connfd = accept(listenfd,(struct sockaddr *)&cliaddr,&clilen);
if (connfd!=-1)
{
FD_SET(connfd, &mastersocket);
if (connfd > fdmax) {
fdmax = connfd;
}
}
}
else
{
//while(1) {
n = recvfrom(i,mesg,1000,0,(struct sockaddr *)&cliaddr,&clilen);
if ((n == -1 /*&& errno == EWOULDBLOCK*/) || (n==0)) {
close (i);
FD_CLR (i, &mastersocket);
if (i == fdmax)
{
while (FD_ISSET(fdmax, &mastersocket) == 0)
fdmax -= 1;
}
// break;
}
//sendto(i,mesg,n,0,(struct sockaddr *)&cliaddr,sizeof(cliaddr));
//write(i , mesg , strlen(mesg)); //both work
//write(i , "" , 1);
printf("-------------------------------------------------------\n");
printf("%d",listenfd);
mesg[n] = 0;
printf("Received the following:\n");
printf("%s",mesg);
printf("-------------------------------------------------------\n");
}
//} /* end of while */
}
} //for i<=fdmax
}
}
client.c
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#define SERVER_PORT 32000
int main (int argc, char *argv[]) {
int sd, rc, i;
struct sockaddr_in localAddr, servAddr;
struct hostent *h;
char message[1000] ;
servAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
servAddr.sin_family = AF_INET;
servAddr.sin_port = htons( SERVER_PORT );
/* create socket */
sd = socket(AF_INET, SOCK_STREAM, 0);
if(sd<0) {
perror("cannot open socket ");
exit(1);
}
/* bind any port number */
localAddr.sin_family = AF_INET;
localAddr.sin_addr.s_addr = htonl(INADDR_ANY);
localAddr.sin_port = htons(0);
rc = bind(sd, (struct sockaddr *) &localAddr, sizeof(localAddr));
if(rc<0) {
printf("%s: cannot bind port TCP %u\n",argv[0],SERVER_PORT);
perror("error ");
exit(1);
}
/* connect to server */
rc = connect(sd, (struct sockaddr *) &servAddr, sizeof(servAddr));
if(rc<0) {
perror("cannot connect ");
exit(1);
}
while(1)
{
printf("Enter message : ");
scanf("%s" , message);
rc = send(sd, message, strlen(message) + 1, 0);
if(rc<0) {
perror("cannot send data ");
close(sd);
exit(1);
}
printf("To_server: data%u sent (%s)\n",strlen(message),message);
}
return 0;
}
I'm new to network programming. I have to write a simple client/server program in C. The server will listen for a connection and the client will connect to the server, send a message, and receive an echo back from the client. We have to update this using select() to handle connections to multiple clients at the same time from the server process. I tried to implement select() on the client side like instructed,but I think I'm having an infinite loop on the client side in if(FD_ISSET(clientSockfd, &readfds)) part.
//client1.c
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <resolv.h>
#include <arpa/inet.h>
const int BUF_SIZE = 512;
int main(int argc, char *argv[]) {
char buf[BUF_SIZE], buf2[BUF_SIZE];
char *msg;
struct sockaddr_in serverInfo;
int clientSockfd, errorCheck, readVal, numfd;
struct hostent *hostName;
fd_set readfds;
//make sure user entered correct arguments when starting client
if(argc != 3)
{
printf("error: must enter 'programName portNumber hostname'\n");
exit(errno);
}
//create socket and error check socket() call
clientSockfd=socket(AF_INET, SOCK_STREAM, 0);
if (clientSockfd == -1)
{
perror("error creating socket");
exit(errno);
}
//assign sockaddr_in info for RemoteAddr
bzero(&serverInfo, sizeof(serverInfo));
serverInfo.sin_family=AF_INET;
hostName=gethostbyname(argv[2]);
if(hostName == NULL)
{
herror("Error when calling gethostbyname()");
exit(errno);
}
memcpy((unsigned char *) &serverInfo.sin_addr, (unsigned char *)hostName->h_addr, hostName->h_length); //copy IP address to be used
serverInfo.sin_port=htons(atoi(argv[1])); //port number to be used, given in command line, must be converted to network byte order
//connect to server side
if(connect(clientSockfd, (struct sockaddr *)&serverInfo, sizeof(serverInfo)) == -1)
{
perror("error when connecting to server");
exit(errno);
}
while(1)
{
FD_ZERO(&readfds); //zero out set
FD_SET(fileno(stdin), &readfds);
FD_SET(clientSockfd, &readfds);
int maxfd = fileno(stdin);
if(maxfd < clientSockfd) maxfd = clientSockfd;
numfd = select(maxfd, &readfds, 0, 0, 0); //call select()
if(numfd > 0)
{
if(FD_ISSET(clientSockfd, &readfds))
{
//make sure buf is empty so it doesnt print extra chars
bzero(buf2, BUF_SIZE);
read(clientSockfd, buf2, BUF_SIZE);
}
if(FD_ISSET(fileno(stdin), &readfds))
{
bzero(buf, BUF_SIZE);
fgets(buf, BUF_SIZE-1, stdin);
printf("echo from server: %s\n", buf);
errorCheck = write(clientSockfd, buf, strlen(buf)+1);
if(errorCheck == -1)
{
perror("error writing");
}
}
}
else if(numfd == 0)
{
perror("Error using select()\n");
exit(0);
}
else
printf("no data\n");
}
//close connection to server
errorCheck = close(clientSockfd);
if(errorCheck == -1)
{
perror("Error closing connection.");
exit(errno);
}
return 0;
}
here is the server..
//server.c
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/socket.h>
#include <resolv.h>
#include <arpa/inet.h>
#include <errno.h>
const int ASSIGNED_PORT = 17000;
const int BUF_SIZE = 512;
int main() {
int serverfd, clientfd;
struct sockaddr_in serverSock; //NOTE: a pointer to sockaddr_in can be cast to a pointer to
// a struct sockaddr - useful for connect()
char buf[BUF_SIZE];
int errorCheck, msgLength;
//create socket with error checking (-1 ret on error)
serverfd = socket(AF_INET, SOCK_STREAM, 0);
if(serverfd < 0 )
{
perror("socket failed.");
exit(errno);
}
//assign sockaddr_in info for server
bzero(&serverSock, sizeof(serverSock)); //set to all 0's
serverSock.sin_family = AF_INET;
serverSock.sin_addr.s_addr = htonl(INADDR_ANY);
serverSock.sin_port = htons(ASSIGNED_PORT);
//bind a name to the socket with error checking (0 ret on success)
errorCheck = bind(serverfd, (struct sockaddr*)&serverSock, sizeof(serverSock));
if(errorCheck < 0 )
{
perror("bind failed.");
exit(errno);
}
//listen for connections with error checking (0 ret on success)
errorCheck = listen(serverfd, 10);
if(errorCheck < 0 )
{
perror("listen failed.");
exit(errno);
}
printf("Listening for connections. Enter CNTRL-c to kill server.\n");
//create infinite loop to accept, read, write, and close connections with error hecking
while(1)
{
//accept the connection from the client
clientfd = accept(serverfd, 0, 0);
if(clientfd == -1)
{
perror("error accepting connection.");
exit(errno);
}
//read data from the client
bzero(buf, BUF_SIZE);
msgLength = read(clientfd, buf, BUF_SIZE-1);
if(msgLength == -1)
{
perror("error reading from client");
close(clientfd);
close(serverfd);
exit(errno);
}
if(buf[0] '\0')
{
printf("connection closing");
exit(0);
}
//print what the client sent
printf("Message from client: %s\n", buf);
//echo back what the client sent
errorCheck = write(clientfd, buf, strlen(buf)+1);
if(errorCheck == -1 )
{
perror("error writing to client");
exit(errno);
}
//close the connection
errorCheck = close(clientfd);
if(errorCheck == -1)
{
perror("error closing connection");
exit(errno);
}
}
errorCheck = close(serverfd);
if(errorCheck==-1)
{
perror("error closing server, exiting program now");
sleep(6);
exit(errno);
}
return 0;
}
I think the problem (or at least, a problem) in your client-side code is that you are passing the magic number 32 to select(). That's incorrect. What you should be passing is the maximum of all of the socket numbers, plus one. For example, something like this:
int maxfd = fileno(stdin);
if (maxfd < clientSockFD) maxfd = clientSockFD;
// further maximizations for other sockets would go here, if you had any other sockets...
numfd = select(maxfd+1, &readfds, 0, 0, 0);
You need to use select() on the server side to handle multiple clients, not on the client side.