Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I'm trying to send data from a server to a client whenever the client executes a recv() command. As the code stands right now, I cannot get the client to print any data it receives. I cannot figure out whether something is wrong with my server or client, so any help would be appreciated. Thanks!
client.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netdb.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#define ECHO_PORT 9999
#define BUF_SIZE 4096
int main(int argc, char* argv[])
{
if (argc != 3)
{
fprintf(stderr, "usage: %s <server-ip> <port>",argv[0]);
return EXIT_FAILURE;
}
char buf[BUF_SIZE];
int status, sock, sock2;
struct addrinfo hints;
memset(&hints, 0, sizeof(struct addrinfo));
struct addrinfo *servinfo; //will point to the results
hints.ai_family = AF_INET; //IPv4
hints.ai_socktype = SOCK_STREAM; //TCP stream sockets
hints.ai_flags = AI_PASSIVE; //fill in my IP for me
if ((status = getaddrinfo(argv[1], argv[2], &hints, &servinfo)) != 0)
{
fprintf(stderr, "getaddrinfo error: %s \n", gai_strerror(status));
return EXIT_FAILURE;
}
if ((sock = socket(servinfo->ai_family, servinfo->ai_socktype, servinfo->ai_protocol)) == -1)
{
fprintf(stderr, "Socket failed");
return EXIT_FAILURE;
}
if ((connect(sock, (struct sockaddr *) servinfo->ai_addr, servinfo->ai_addrlen)) != 0)
{
fprintf(stderr, "Connection failed");
return EXIT_FAILURE;
}
if ((sock2 = socket(servinfo->ai_family, servinfo->ai_socktype, servinfo->ai_protocol)) == -1)
{
fprintf(stderr, "Socket failed");
return EXIT_FAILURE;
}
if ((connect(sock2, (struct sockaddr *) servinfo->ai_addr, servinfo->ai_addrlen)) != 0)
{
fprintf(stderr, "Connection failed");
return EXIT_FAILURE;
}
while (1) {
//char msg[BUF_SIZE] = "ashudfshuhafhu";
//char msg[BUF_SIZE];
//fgets(msg, BUF_SIZE, stdin);
//int i = 2;
//if (strlen(msg) == i)
// break;
int bytes_received;
// fprintf(stdout, "Sending %s", msg);
//send(sock, msg , strlen(msg), 0);
if((bytes_received = recv(sock, buf, BUF_SIZE, 0)) > 1)
{
buf[bytes_received] = '\0';
fprintf(stdout, "Received %s", buf);
}
}
freeaddrinfo(servinfo);
close(sock);
return EXIT_SUCCESS;
}
Server.c
#include <netinet/in.h>
#include <netinet/ip.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
#define ECHO_PORT 9999
#define BUF_SIZE 4096
int close_socket(int sock)
{
if (close(sock))
{
fprintf(stderr, "Failed closing socket.\n");
return 1;
}
return 0;
}
int main(int argc, char* argv[])
{
int sock, client_sock;
ssize_t readret;
socklen_t cli_size;
struct timeval tv;
struct sockaddr_in addr, cli_addr;
char buf[BUF_SIZE] = "wetwetwetwetwetwetwetwet";
fd_set readfds, writefds;
fd_set activereadfds, activewritefds;
cli_size = sizeof(&cli_addr);
tv.tv_sec = 5;
tv.tv_usec = 0;
fprintf(stdout, "----- Echo Server -----\n");
/* all networked programs must create a socket */
if ((sock = socket(PF_INET, SOCK_STREAM, 0)) == -1)
{
fprintf(stderr, "Failed creating socket.\n");
return EXIT_FAILURE;
}
addr.sin_family = AF_INET;
addr.sin_port = htons(ECHO_PORT);
addr.sin_addr.s_addr = INADDR_ANY;
/* servers bind sockets to ports---notify the OS they accept connections */
if (bind(sock, (struct sockaddr *) &addr, sizeof(addr)))
{
close_socket(sock);
fprintf(stderr, "Failed binding socket.\n");
return EXIT_FAILURE;
}
if (listen(sock, 5))
{
close_socket(sock);
fprintf(stderr, "Error listening on socket.\n");
return EXIT_FAILURE;
}
FD_ZERO(&readfds);
FD_SET(sock, &activereadfds);
while (1)
{
fprintf(stdout,"in here.\n");
readfds = activereadfds;
writefds = activewritefds;
FD_ZERO(&activereadfds);
FD_ZERO(&activewritefds);
if (select(51, &readfds, &writefds, NULL, &tv) < 0)
{
perror("select");
return EXIT_FAILURE;
}
for (int i = 0; i < 10; ++i)
{
if (FD_ISSET (i, &readfds))
{
if (i == sock)
{
fprintf(stdout, "main loop. \n");
client_sock = accept(sock,
(struct sockaddr *) &cli_addr, &cli_size);
FD_SET(client_sock, &activereadfds);
FD_SET(client_sock, &activewritefds);
if (client_sock < 0)
{
perror("accept");
return EXIT_FAILURE;
}
} else {
fprintf(stdout, "second loop \n");
readret = send(i,buf, strlen(buf),0);
if (readret < 0)
fprintf(stdout, "yay");
}
}
if (FD_ISSET(i, &writefds))
{ fprintf(stdout, "ugh \n");
readret = send(i,buf,BUF_SIZE,0);
//if (readret > 0)
//while((readret = recv(i, buf, BUF_SIZE, 0)) >= 1)
// {
//if (send(i, buf, readret, 0) != readret)
//{
// close_socket(i);
// close_socket(sock);
// fprintf(stderr, "Error sending to client.\n");
// return EXIT_FAILURE;
//}
}
}
}
close_socket(sock);
return EXIT_SUCCESS;
}
Your server is sending only when the socket is ready for reading, and as the client is never sending, the server isn't either. The server send should happen when the client socket turns up in the writefds, although actually this isn't the correct way to use that feature. Really you should just send, and only add into and worry about writefds if send() caused EAGAIN/EWOULDBLOCK.
You could be getting an undetected error in the client:
if((bytes_received = recv(sock, buf, BUF_SIZE, 0)) > 1)
{
buf[bytes_received] = '\0';
fprintf(stdout, "Received %s", buf);
}
This should continue:
else if (bytes_received == 0)
{
fprintf(stdout, "peer disconnected\n");
break;
}
else // < 0: error
{
fprintf(stdout, "recv() error %s\n", strerror(errno));
break;
}
You need to print the actual error like this whenever you get an error from a system call.
Related
I am a C beginner. I want to send a file by TCP. The client reads content from a txt file and sent it to server. Read method is ok. It reads the specified bytes from the file. Send method dose not throw any exception. However the server receives nothing. I try to solve it for a whole day. I fail.
Please help me check what is wrong with my code.
As comment advice, I edit my code again. Now there are two problem. One is that in the client loop the return values from client fread() and send() is greater than 0 for the first two times while the server accept() is still blcoked without getting message from client.
The second problem. In the third client loop, the return value of client fread() is still greater than 0, but the return value of send() is -1.I try to open the file in binary mode rb instead of r. It is the same problem.
the edited client code:
#include <stdio.h>
#include <winsock.h>
#include <time.h>
#pragma comment(lib, "WS2_32.lib")
#define MAXLINE 1024*4
SOCKET sockClient;// = socket(AF_INET,SOCK_DGRAM,0);
SOCKADDR_IN servAddr;
int main(void) {
WSADATA wsd;
FILE *fp;
int read_len;
char buf2[MAXLINE];
time_t t_start, t_end;
if ((fp = fopen("file.txt", "r")) == NULL) {
perror("Open file failed\n");
exit(0);
}
if (WSAStartup(MAKEWORD(2, 2), &wsd) != 0) {
printf("WSAStartup failed !\n");
return 1;
}
sockClient = socket(AF_INET, SOCK_STREAM, 0);
servAddr.sin_family = AF_INET;
servAddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
servAddr.sin_port = htons(5000);
/* connect the server commanted by guoqingbo*/
int i_ret = connect(sockClient, (struct sockaddr *) &servAddr, sizeof(struct sockaddr));
if (-1 == i_ret) {
perror("Connect socket failed!\n");
exit(0);
}
printf("client starts\n");
t_start = time(NULL);
while (1) {
read_len = fread(buf2, sizeof(char), MAXLINE, fp);
if (read_len < 0) {
perror("read data failed\n");
break;
} else if (read_len == 0) {
printf("read finished\n");
}
int send_len = send(sockClient, buf2, read_len, 0);
if (send_len < 0) {
perror("Send data failed\n");
exit(0);
} else if (send_len == 0) {
printf("send finished\n");
break;
}
}
t_end = time(NULL);
printf("The time used %f s\n", difftime(t_end, t_start));
fclose(fp);
closesocket(sockClient);
WSACleanup();
return 0;
}
the edited server code:
#include <stdio.h>
#include <WINSOCK2.H>
#include <strings.h>
#include <stdlib.h>
#pragma comment(lib, "WS2_32.lib")
#define BUF_SIZE 1024*4
SOCKET socketSrv;
SOCKADDR_IN addrSrv;
SOCKADDR_IN addrClient;
char buf[BUF_SIZE];
int main(void) {
WSADATA wsd;
int nRet;
int recv_len;
FILE *fp;
if ((fp = fopen("file.txt", "w")) == NULL) {
perror("Creat file failed");
exit(0);
}
if (WSAStartup(MAKEWORD(2, 2), &wsd) != 0) {
printf("WSAStartup failed !\n");
return 1;
}
socketSrv = socket(AF_INET, SOCK_STREAM, 0);
int len = sizeof(SOCKADDR);
ZeroMemory(buf, BUF_SIZE);
addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
addrSrv.sin_family = AF_INET;
addrSrv.sin_port = htons(5000);
nRet = bind(socketSrv, (SOCKADDR *) &addrSrv, sizeof(SOCKADDR));
if (SOCKET_ERROR == nRet) {
printf("bind failed !\n");
closesocket(socketSrv);
WSACleanup();
return -1;
}
if (SOCKET_ERROR == listen(socketSrv, 10)) {
printf("Server Listen Failed: %d", WSAGetLastError());
exit(1);
}
printf("server started..\n");
while (1) {
SOCKET m_New_Socket = accept(socketSrv, (SOCKADDR *) &addrClient, &len);
if (SOCKET_ERROR == m_New_Socket) {
printf("Server Accept Failed: %d", WSAGetLastError());
break;
}
if (recv_len = recv(socketSrv, buf, BUF_SIZE, 0) < 0) {
printf("Server Receive Data Failed!");
break;
}
int write_length = fwrite(buf, sizeof(char), recv_len, fp);
if (write_length < recv_len) {
printf("File write failed\n");
break;
}
}
fclose(fp);
closesocket(socketSrv);
WSACleanup();
return 0;
}
So i have a client.c file on a computer in my lan and a server.c file on another computer. Essentially i start the server.c file and specify what port it needs to listen to as it waits. I think run my client.c command by specifying the address were server.c is running and what port to send my command on. the only thing my client sends is a filename (call it test.txt). My server is then to take that command using recv() from the C socket protocols, and i would like to be able to read that file and send that output back to my client so that it outputs to my clients terminal. I have figured out how to send the file as that is easy but i am having a hard time understanding how I can do this task with sockets. Do i just need to issue a write command using send() ? Do i need to read the file and send line by line to the socket ? if thats the case and say i have 10 clients do i need to use a semaphore or mutex to make sure that the output is sent fully before moving on to the next client request?
The code does more than just what I am asking for it also has a logging feature. and i have been using
http://beej.us/guide/bgnet/html/ as a guide. But its just sending back the contents of the file that is on the server.c machine to the client.c output that is kinda causing me to go in circles.
so in theory it should look something like this on the client side
./client 129.65.128.82:4443 bigfile
...entire contents of bigfile should appear here...
Here is my Server.c Code and Client.c (at the bottom for reference)
Server.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <signal.h>
#include <time.h>
#include <sys/stat.h>
#define PORT "4443" // the port users will be connecting to
#define BACKLOG 10 // how many pending connections queue will hold
size_t getFilesize(const char* filename) {
struct stat st;
if(stat(filename, &st) != 0) {
return 0;
}
return st.st_size;
}
void fileOutput(char *filename){
FILE *fptr;
char c;
//int check = checkFilename(filename);
fptr = fopen(filename,"r");
printf("We opened the file\n");
if (fptr == NULL)
{
printf("Cannot open file \n");
exit(0);
}
printf("HereWe ARE\n");
// Read contents from file
c = fgetc(fptr);
while (c != EOF)
{
printf ("%c", c);
c = fgetc(fptr);
}
fclose(fptr);
}
void sigchld_handler(int s)
{
(void)s; // quiet unused variable warning
// waitpid() might overwrite errno, so we save and restore it:
int saved_errno = errno;
while ( waitpid(-1, NULL, WNOHANG) > 0 );
errno = saved_errno;
}
void argumentCheck(int n){
if (n < 2) {
fprintf(stderr,"Usage: server port # example port 4443\n");
exit(1);
}
}
// get sockaddr, IPv4 or IPv6:
void *get_in_addr(struct sockaddr *sa)
{
if ( sa->sa_family == AF_INET ) {
return &(((struct sockaddr_in*)sa)->sin_addr);
}
return &(((struct sockaddr_in6*)sa)->sin6_addr);
}
void logfile(FILE *fp,char *s,char *port,char *buffer,int r){
time_t t = time((time_t*) NULL);
struct tm *tm = localtime(&t);
char tc[256];
strftime(tc, 256, "%Y-%m-%d %H:%M:%S", tm);
fprintf(fp,"[%s] %s:%s %s %d\n",tc,s,port,buffer,r);
}
int main(int argc, char **argv)
{
//Log file creation
FILE *fp;
fp = fopen("log","a");
///////
///File Size///
//////////////
argumentCheck(argc);
int sockfd, new_fd; // listen on sockfd, new connection on new_fd
struct addrinfo hints, *servinfo, *p;
struct sockaddr_storage their_addr; // connector's address information
socklen_t sin_size;
struct sigaction sa;
int yes=1;
char s[INET6_ADDRSTRLEN];
int rv;
char *inputPort = argv[1];
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE; // use my IP
if ( (rv = getaddrinfo(NULL, inputPort, &hints, &servinfo)) != 0 ) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
return 1;
}
// loop through all the results and bind to the first we can
for(p = servinfo; p != NULL; p = p->ai_next) {
if ( (sockfd = socket(p->ai_family, p->ai_socktype,
p->ai_protocol)) == -1 ) {
perror("server: socket");
continue;
}
if ( setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes,
sizeof(int)) == -1 ) {
perror("setsockopt");
exit(1);
}
if ( bind(sockfd, p->ai_addr, p->ai_addrlen) == -1 ) {
close(sockfd);
perror("server: bind");
continue;
}
break;
}
freeaddrinfo(servinfo); // all done with this structure
if ( p == NULL ) {
fprintf(stderr, "server: failed to bind\n");
exit(1);
}
// listen allows queue of up to BACKLOG number
if ( listen(sockfd, BACKLOG) == -1 ) {
perror("listen");
exit(1);
}
sa.sa_handler = sigchld_handler; // reap all dead processes
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART;
if ( sigaction(SIGCHLD, &sa, NULL) == -1 ) {
perror("sigaction");
exit(1);
}
printf("server: waiting for connections...\n");
while ( 1 ) { // main accept() loop
sin_size = sizeof their_addr;
new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size);
if ( new_fd == -1 ) {
perror("accept");
continue;
}
inet_ntop(their_addr.ss_family,
get_in_addr((struct sockaddr *)&their_addr),
s, sizeof s);
//printf("server: got connection from %s\n", s);
if ( !fork() ) { // this is the child process
char buf[1024];
close(sockfd); // child doesn't need the listener
printf("this is the sizeof buf %ld\n",sizeof(buf));
recv(new_fd,buf, sizeof(buf),0);
int size = getFilesize(buf);
logfile(fp,s,inputPort,buf,size);
fileOutput(buf);
if ( send(new_fd, buf, size, 0) == -1)
perror("send");
printf("%s\n",buf);
close(new_fd);
exit(0);
}
close(new_fd); // parent doesn't need this
}
fclose(fp);
return 0;
}
Client.c code:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#define PORT "4443" // the port client will be connecting to
// get sockaddr, IPv4 or IPv6:
void *get_in_addr(struct sockaddr *sa)
{
if ( sa->sa_family == AF_INET ) {
return &(((struct sockaddr_in*)sa)->sin_addr);
}
return &(((struct sockaddr_in6*)sa)->sin6_addr);
}
int main(int argc, char **argv)
{
if ( argc < 2 ) {
fprintf(stderr,"Usage: client ipaddr:port # example 129.65.128.82:4443 [filename]\n");
exit(1);
}
int sockfd, numbytes;
char buf[BUFSIZ];
struct addrinfo hints, *servinfo, *p;
int rv;
char s[INET_ADDRSTRLEN];
// Used to extract ipv4 and socket seperatly
char *ip_address = strtok(argv[1],":");
char *ip_port = strtok(NULL,":");
memset(&hints, 0, sizeof(hints)); // make sure the struct is empty
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
if ( (rv = getaddrinfo(ip_address, ip_port, &hints, &servinfo)) != 0 ) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
return 1;
}
// loop through all the results and connect to the first we can
for(p = servinfo; p != NULL; p = p->ai_next) {
if ( (sockfd = socket(p->ai_family,
p->ai_socktype,
p->ai_protocol)) == -1 ) {
perror("client: socket");
continue;
}
if ( connect(sockfd, p->ai_addr, p->ai_addrlen) == -1 ) {
perror("client: connect");
close(sockfd);
continue;
}
break;
}
if ( p == NULL ) {
fprintf(stderr, "client: failed to connect\n");
return 2;
}
//printf("we are stopping here");
inet_ntop(p->ai_family, get_in_addr((struct sockaddr *)p->ai_addr),
s, sizeof s);
printf("client: connecting to %s\n", s);
freeaddrinfo(servinfo); // all done with this structure
//strcpy(buf, "Hello World.\n");
//printf("this is argv2 size %ld\n",strlen(argv[2]));
strcpy(buf,argv[2]);
//printf("this is buf size %ld\n",strlen(buf));
//write(1, "client send: ", strlen("client send: "));
//write(1, buf, strlen(buf));
send(sockfd, buf, sizeof(buf), 0);
if ( (numbytes = recv(sockfd, buf, sizeof(buf)-1, 0)) == -1 ) {
printf("this is numbytes %d\n",numbytes);
perror("recv");
exit(1);
}
printf("this is numbytes %d\n",numbytes);
buf[numbytes] = '\0';
//write(1, "client recv: ", strlen("client recv: "));
//write(1, buf, strlen(buf));
close(sockfd);
return 0;
}
enter code here
I'm facing a problem with sockets programming in C.
I've coded a server where multiple clients can connect and send messages in a chatroom but i don't know how to connect two clients two by two.
example:
Client A connect to the Server but must wait in a queue waiting for Client B to connect.
Client C connect but must wait in a queue waiting for Client D to connect.
Every pair of clients must be in their specific chatroom, do I need to share the fd between the two sockets of the 2 clients or link between the two sockets.
I thought about using another way by using the function accept() twice before I fork() but I have to use child processes for that.
Here is my server code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/select.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#define PORT "8888"
void *get_in_addr(struct sockaddr *sa)
{
if (sa->sa_family == AF_INET) {
return &(((struct sockaddr_in*)sa)->sin_addr);
}
return &(((struct sockaddr_in6*)sa)->sin6_addr);
}
int main(void)
{
fd_set master;
fd_set read_fds;
int fdmax;
int listener;
int newfd;
struct sockaddr_storage remoteaddr;
socklen_t addrlen;
char buf[256];
int nbytes;
char remoteIP[INET6_ADDRSTRLEN];
int yes=1;
int i, j, rv;
struct addrinfo hints, *ai, *p;
FD_ZERO(&master);
FD_ZERO(&read_fds);
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;
if ((rv = getaddrinfo(NULL, PORT, &hints, &ai)) != 0) {
fprintf(stderr, "Server msg: %s\n", gai_strerror(rv));
exit(1);
}
for(p = ai; p != NULL; p = p->ai_next)
{
listener = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
if (listener < 0) {
continue;
}
setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int));
if (bind(listener, p->ai_addr, p->ai_addrlen) < 0) {
close(listener);
continue;
}
break;
}
if (p == NULL) {
fprintf(stderr, "Server msg: bind failed\n");
exit(2);
}
freeaddrinfo(ai);
puts("Bind success");
if (listen(listener, 10) == -1)
{
perror("listen");
exit(3);
}
puts("Server listening ...");
FD_SET(listener, &master);
fdmax = listener;
for(;;)
{
read_fds = master;
if (select(fdmax+1, &read_fds, NULL, NULL, NULL) == -1)
{
perror("select");
exit(4);
}
for(i = 0; i <= fdmax; i++)
{
if (FD_ISSET(i, &read_fds))
{
if (i == listener)
{
addrlen = sizeof remoteaddr;
newfd = accept(listener,
(struct sockaddr *)&remoteaddr,
&addrlen);
if (newfd == -1)
{
perror("accept");
}
else
{
FD_SET(newfd, &master);
if (newfd > fdmax)
{
fdmax = newfd;
}
printf("Server msg: new connection from %s on "
"socket %d\n", inet_ntop(remoteaddr.ss_family,
get_in_addr((struct sockaddr*)&remoteaddr),
remoteIP, INET6_ADDRSTRLEN), newfd);
}
}
else
{
if ((nbytes = recv(i, buf, sizeof buf, 0)) <= 0)
{
if (nbytes == 0)
{
printf("Server msg: socket %d lost\n", i);
}
else
{
perror("recv");
}
close(i);
FD_CLR(i, &master);
}
else
{
for(j = 0; j <= fdmax; j++)
{
if (FD_ISSET(j, &master))
{
if (j != listener && j != i)
{
if (send(j, buf, nbytes, 0) == -1)
{
perror("send");
}
}
}
}
}
}
}
}
}
return 0;
}
And here is my client code:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/select.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <pthread.h>
#include <arpa/inet.h>
#define PORT "8888"
#define MAXDATASIZE 100
#define MAXNAMESIZE 25
void *receive_handler(void *);
void *get_in_addr(struct sockaddr *sa)
{
if (sa->sa_family == AF_INET) {
return &(((struct sockaddr_in*)sa)->sin_addr);
}
return &(((struct sockaddr_in6*)sa)->sin6_addr);
}
int main(int argc, char *argv[])
{
char message[MAXDATASIZE];
char nickName[MAXNAMESIZE];
int sockfd;
char sBuf[MAXDATASIZE];
struct addrinfo hints, *servinfo, *p;
int rv;
char s[INET6_ADDRSTRLEN];
if (argc != 2) {
fprintf(stderr,"Usage: ./client address\n");
exit(1);
}
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
if ((rv = getaddrinfo(argv[1], PORT, &hints, &servinfo)) != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
return 1;
}
for(p = servinfo; p != NULL; p = p->ai_next) {
if ((sockfd = socket(p->ai_family, p->ai_socktype,
p->ai_protocol)) == -1) {
perror("Client: socket");
continue;
}
if (connect(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
close(sockfd);
perror("Client: connect");
continue;
}
break;
}
if (p == NULL) {
fprintf(stderr, "Client: connection failed\n");
return 2;
}
inet_ntop(p->ai_family, get_in_addr((struct sockaddr *)p->ai_addr),
s, sizeof s);
printf("Client: connection to %s\n", s);
freeaddrinfo(servinfo);
puts("Give your username:");
memset(&nickName, sizeof(nickName), 0);
memset(&message, sizeof(message), 0);
fgets(nickName, MAXNAMESIZE, stdin);
pthread_t recv_thread;
if( pthread_create(&recv_thread, NULL, receive_handler, (void*)(intptr_t) sockfd) < 0)
{
perror("Failed on thread creation");
return 1;
}
puts("Connection established");
puts("Welcome!\n");
puts("[Type '/quit' to quit the chatroom]");
for(;;)
{
char temp[6];
memset(&temp, sizeof(temp), 0);
memset(&sBuf, sizeof(sBuf), 0);
fgets(sBuf, 100, stdin);
if(sBuf[0] == '/' &&
sBuf[1] == 'q' &&
sBuf[2] == 'u' &&
sBuf[3] == 'i' &&
sBuf[4] == 't')
return 1;
int count = 0;
while(count < strlen(nickName))
{
message[count] = nickName[count];
count++;
}
count--;
message[count] = ':';
count++;
for(int i = 0; i < strlen(sBuf); i++)
{
message[count] = sBuf[i];
count++;
}
message[count] = '\0';
if(send(sockfd, message, strlen(message), 0) < 0)
{
puts("Sent failed");
return 1;
}
memset(&sBuf, sizeof(sBuf), 0);
}
pthread_join(recv_thread , NULL);
close(sockfd);
return 0;
}
void *receive_handler(void *sock_fd)
{
int sFd = (intptr_t) sock_fd;
char buffer[MAXDATASIZE];
int nBytes;
for(;;)
{
if ((nBytes = recv(sFd, buffer, MAXDATASIZE-1, 0)) == -1)
{
perror("recv");
exit(1);
}
else
buffer[nBytes] = '\0';
printf("%s", buffer);
}
}
Yes, in my opinion you can use two accept and then call a fork() or, even better, a new thread. You can create a new process/thread for each pair of connections.
What do you mean sharing the fd? You mean sending a fd of one client to another? In this case NO
You can keep, in the thread function, a mapping between the two clients to know which clients are paired. When receiving a message from one client, thanks to the mapping, you know which client you are supposed to send the message to.
I think the rest depends on further details you should specify in your question.
Let me know
If each client can both send and receive you might want to use multithreading on client-side too: one to send and one to receive.
This is my client program that requests files from the server:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#define SERVER_PORT 5959
#define MAX_LINE 512
void setstring(char *str){
str[MAX_LINE-1]='\0';
}
int main(int argc, char * argv[]){
FILE *fp;
struct hostent *hp;
struct sockaddr_in sin;
char *host;
char filename[MAX_LINE],buf[MAX_LINE],reply[MAX_LINE],rec_line[MAX_LINE];
int s;
char msg[MAX_LINE];
int len,new_len,rec_file;
if (argc==2) {
host = argv[1];
}
else {
fprintf(stderr, "usage: simplex-talk host\n");
exit(1);
}
/* translate host name into peer's IP address */
hp = gethostbyname(host);
if (!hp) {
fprintf(stderr, "simplex-talk: unknown host: %s\n", host);
exit(1);
}
else
printf("Client's remote host: %s\n", argv[1]);
/* build address data structure */
bzero((char *)&sin, sizeof(sin));
sin.sin_family = AF_INET;
bcopy(hp->h_addr, (char *)&sin.sin_addr, hp->h_length);
sin.sin_port = htons(SERVER_PORT);
/* active open */
if ((s = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
perror("simplex-talk: socket");
exit(1);
}
else
printf("Client created socket.\n");
int send_file_name,rec_msg;
if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0)
{
perror("simplex-talk: connect");
close(s);
exit(1);
}
else{
printf("Client connected.\n");
/* main loop: get and send lines of text */
printf("Hello from server\n");
while(!(strcmp(reply,"bye")==0)){
printf("Enter the file name:\n");
scanf("%s",filename);
setstring(filename);
send_file_name=send(s,filename,strlen(filename)+1,0);
if(send_file_name<0)
fputs("Error sending filename",stdout);
rec_msg=recv(s,msg,sizeof(msg),0);
if(strcmp(msg,"File not found")==0)
printf("File not found\n");
else{
printf("%s\n",msg);
fp=fopen(filename,"w");
printf("CP1\n");
if(rec_file=recv(s,rec_line,sizeof(rec_line),0)>0){
printf("CP2");
printf("String recieved:%s\n",rec_line);
if(len=fwrite(rec_line,1,rec_file+1,fp)>0)
printf("Recieved file\n");
else
printf("Error writing to file\n");
}
else
printf("Not recieved\n");
}
printf("Enter 'bye' to terminate requesting files\n");
scanf("%s",reply);
}
}
return 0;
}
This is my server program that accepts request for files from the client:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#define SERVER_PORT 5959
#define MAX_PENDING 5
#define MAX_LINE 256
void setstring(char* str){
str[MAX_LINE-1]='\0';
}
int main(){
FILE *fp;
struct sockaddr_in sin;
char buf[MAX_LINE],msg[MAX_LINE],*rec_line;
int len;
int s, new_s,count;
char str[INET_ADDRSTRLEN];
int error_file,send_msg,read_line,send_file;
bzero((char *)&sin, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = inet_addr("0.0.0.0");
sin.sin_port = htons(SERVER_PORT);
/* setup passive open */
if ((s = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
perror("simplex-talk: socket");
exit(1);
}
inet_ntop(AF_INET, &(sin.sin_addr), str, INET_ADDRSTRLEN);
printf("Server is using address %s and port %d.\n", str, SERVER_PORT);
if ((bind(s, (struct sockaddr *)&sin, sizeof(sin))) < 0) {
perror("simplex-talk: bind");
exit(1);
}
else
printf("Server bind done.\n");
listen(s, MAX_PENDING);
/* wait for connection, then receive and print text */
while(1) {
if ((new_s = accept(s, (struct sockaddr *)&sin, &len)) < 0) {
perror("simplex-talk: accept");
exit(1);
}
printf("Server Listening.\n");
printf("Greetings\n");
int rec_file_name=recv(new_s,buf,sizeof(buf),0);
if(rec_file_name>0)
printf("File requested:%s\n",buf);
fp=fopen(buf,"r");
if(fp==NULL)
{
fputs("File not found\n",stdout);
strcpy(buf,"File not found");
if(error_file=send(new_s,buf,strlen(buf)+1,0)>0)
fputs("Successfully send error message to client\n",stdout);
}
else{
bzero(buf,MAX_LINE);
printf("File found :) \n");
strcpy(buf,"OK");
if(send_msg=send(new_s,buf,strlen(buf)+1,0)>0)
fputs("File found message sent to client\n",stdout);
fseek(fp,0,SEEK_END);
int file_size=ftell(fp);
fseek(fp,0,SEEK_SET);
printf("File size:%d\n",file_size);
rec_line=(char *)malloc(sizeof(char)*(file_size));
read_line=fread(rec_line,1,file_size+1,fp);
printf("File read: %s\n",rec_line);
if(send_file=send(new_s,rec_line,strlen(rec_line)+1,0)>0)
printf("File string sent to client\n");
}
}
close(new_s);
}
The problem is that in the client, my second recv() call, where it is supposed to receive the contents of a file, shows nothing. The programs halts at that point, but the server programs displays that it has sent the file contents. The client doesn't receive it.
The basic problem is that you're not checking the return values to see how much data you actually sent and received. So when the client calls:
rec_msg=recv(s,msg,sizeof(msg),0);
it will receive up to sizeof(msg) (512) bytes, which is probably both the OK message the server is sending AND the file contents (after the NUL). Which means when it does a second recv call to get the contents, it blocks, because it already read the contents in the first call and there's no more data waiting in the receive buffer.
Your error-checking is haphazard, and consequently you're certainly missing a problem that occurs before the behavior you're observing. I recommend you follow RW Steven's idiom:
int n;
if( (n = recv(new_s, buf, sizeof(buf), 0)) < 0 ) {
err(EXIT_FAILURE, "recv %d", __LINE__);
}
Test every function call, and handle every error. For simple programs, just call err(3) on error. Do that consistently, and the program's behavior will be much less mysterious (if still occasionally surprising). And don't be afraid of the spacebar! It's easy to hit, and easier still to read.
My other bit of advice, if I may, concerns
int send_file_name,rec_msg;
Names like that are confusing. A name is almost never an integer. For I/O sizes, just use one simple name like n, len, or size. Even if you don't care for yourself, you want to care before publishing your question in an open forum. Otherwise, when people see
send_file_name=send(s,filename,strlen(filename)+1,0);
they may think send is some function other than send(2), or that the person asking the question was careless.
The main problem I see is that neither the client nor the server are handling socket I/O correctly in general. They are not handling the cases where reads and writes transfer fewer bytes then requested, you need to loop the I/O. And the client is reading too many bytes from the server anyway, which is why your second recv() is blocking. And you are relying on a disconnect to indicate the end of the file has been reached, but that does not allow the client to do adequate error checking to know if the full file was actually received or not.
Also, when sending the content of a file, the server is attempting to read the entire file into memory (bad!), not doing adequate error checking on the file I/O, and it is treating the file content as text instead of as binary (don't use strlen() on binary data!).
Try something more like this instead:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#define SERVER_PORT 5959
#define MAX_LINE 512
int sendstring(int sock, const char *str) {
if (!str) str = "";
int len = strlen(str) + 1;
do {
int ret = send(sock, str, len, 0);
if (ret <= 0) return -1;
str += ret;
len -= ret;
}
while (len > 0);
return 0;
}
int readbuf(int sock, void *buf, int buflen) {
char *pbuf = (char*) buf;
while (buflen > 0) {
int len = recv(sock, pbuf, buflen, 0);
if (len <= 0) return -1;
pbuf += len;
buflen -= len;
}
return 0;
}
int readstring(int sock, char *str, int maxlen) {
while (maxlen > 0) {
if (recv(sock, str, 1, 0) <= 0) return -1;
if (*str == '\0') return 0;
++str;
--maxlen;
}
return -2;
}
int readfile(int sock, int fd) {
int filesize;
char buf[MAX_LINE];
if (readbuf(sock, &filesize, sizeof(filesize)) < 0) return -1;
filesize = ntohl(filesize);
while (filesize > 0) {
int len = readbuf(sock, buf, min(sizeof(buf), filesize));
if (len < 0) return -1;
if (fwrite(buf, len, 1, fp) != 1) return -2;
filesize -= len;
}
return 0;
}
int main(int argc, char * argv[]) {
char filename[MAX_LINE], reply[MAX_LINE];
if (argc != 2) {
fprintf(stderr, "usage: simplex-talk host\n");
exit(1);
}
char *host = argv[1];
/* translate host name into peer's IP address */
struct hostent *hp = gethostbyname(host);
if (!hp) {
fprintf(stderr, "simplex-talk: unknown host: %s\n", host);
exit(1);
}
if (hp->h_addrtype != AF_INET) {
fprintf(stderr, "simplex-talk: unsupported address type %d for host: %s\n", hp->h_addrtype, host);
exit(1);
}
/* build address data structure */
struct sockaddr_in sin;
bzero((char *)&sin, sizeof(sin));
sin.sin_family = AF_INET;
bcopy(hp->h_addr, &sin.sin_addr, hp->h_length);
sin.sin_port = htons(SERVER_PORT);
printf("Host's remote IP: %s\n", inet_ntoa(&sin.sin_addr));
/* active open */
int s = socket(PF_INET, SOCK_STREAM, 0);
if (s < 0) {
perror("simplex-talk: socket");
exit(1);
}
printf("Client created socket.\n");
if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0)
{
perror("simplex-talk: connect");
close(s);
exit(1);
}
printf("Client connected.\n");
/* main loop: get and send lines of text */
do {
printf("Enter the file name ('bye' to quit):\n");
if (scanf("%512s", filename) != 1) {
printf("Error reading filename\n");
break;
}
if (strcmp(filename, "bye") == 0) {
sendstring(s, "bye");
break;
}
if (sendstring(s, filename) < 0) {
printf("Error sending filename\n");
break;
}
if (readstring(s, reply, sizeof(reply)) < 0) {
printf("Error reading reply\n");
break;
}
if (strcmp(reply, "OK") != 0) {
printf("%s\n", reply);
if (strcmp(reply, "bye") == 0) break;
continue;
}
FILE *fp = fopen(filename, "wb");
if (!fp) {
printf("Error opening file\n");
break;
}
printf("Receiving file\n");
int ret = readfile(s, fd);
fclose(fp);
if (ret < 0) {
if (ret == -2)
printf("Error writing file\n");
else
printf("Error reading file\n");
break;
}
printf("Received file\n");
}
while (1);
close(s);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#define SERVER_PORT 5959
#define MAX_PENDING 5
#define MAX_LINE 512
int sendbuf(int sock, void *buf, int buflen) {
char *pbuf = (char*) buf;
while (len > 0) {
int len = send(sock, pbuf, buflen, 0);
if (len <= 0) return -1;
pbuf += len;
buflen -= len;
}
return 0;
}
int sendstring(int sock, const char *str) {
if (!str) str = "";
return sendbuf(sock, str, strlen(str) + 1);
}
int sendfile(int sock, int fd) {
char buf[MAX_LINE];
struct stat s;
if (fstat(fd, &s) < 0) return -2;
int pos = ftell(fp);
if (pos == -1) return -2;
int file_size = s.st_size - pos;
int tmp_file_size = htonl(file_size);
if (sendbuf(sock, &tmp_file_size, sizeof(tmp_file_size)) < 0) return -1;
while (file_size > 0) {
int len = fread(buf, 1, min(sizeof(buf), file_size), fp);
if (len < 1) return -2;
if (sendbuf(sock, buf, len) < 0) return -1;
file_size -= len;
}
return 0;
}
int readstring(int sock, char *str, int maxlen) {
while (maxlen > 0) {
if (recv(sock, str, 1, 0) <= 0) return -1;
if (*str == '\0') return 0;
++str;
--maxlen;
}
return -2;
}
int main() {
char msg[MAX_LINE];
struct sockaddr_in sin;
bzero((char *)&sin, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = INADDR_ANY;
sin.sin_port = htons(SERVER_PORT);
/* setup passive open */
int s = socket(PF_INET, SOCK_STREAM, 0);
if (s < 0) {
perror("simplex-talk: socket");
exit(1);
}
printf("Server is using address %s and port %d.\n", inet_ntoa(&(sin.sin_addr)), SERVER_PORT);
if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
perror("simplex-talk: bind");
close(s);
exit(1);
}
printf("Server bind done.\n");
if (listen(s, MAX_PENDING) < 0) {
perror("simplex-talk: listen");
close(s);
exit(1);
}
printf("Server Listening.\n");
/* wait for connection, then receive and print text */
do {
int len = sizeof(sin);
int cli_s = accept(s, (struct sockaddr *)&sin, &len);
if (cli_s < 0) {
perror("simplex-talk: accept");
close(s);
exit(1);
}
printf("Client connected\n");
do {
if (readstring(cli_s, msg, sizeof(msg)) < 0) {
printf("Error reading request\n");
break;
}
if (strcmp(msg, "bye") == 0) break;
printf("File requested: %s\n", msg);
FILE *fp = fopen(msg, "rb");
if (!fp)
{
printf("Cannot open file\n");
if (sendstring(cli_s, "Cannot open file") < 0) {
printf("Error sending reply\n");
break;
}
continue;
}
printf("File found :) \n");
if (sendstring(cli_s, "OK") < 0) {
printf("Error sending reply\n");
fclose(fp);
break;
}
ret = sendfile(cli_s, fp);
fclose(fp);
if (ret < 0) {
printf("Error sending file\n");
break;
}
printf("File sent to client\n");
}
while (1);
close(cli_s);
}
while (1);
close(s);
return 0;
}
I am attempting to write a simple chat program where one user can connect to a host. The two should be able to talk to each other (they might interrupt each other but that is ok). I am having difficulties with select(). Here is the code:
client.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#define MAXDATASIZE 1024 // max number of bytes we can get at once
// get sockaddr, IPv4 or IPv6:
void *get_in_addr(struct sockaddr *sa) {
if (sa->sa_family == AF_INET) {
return &(((struct sockaddr_in*) sa)->sin_addr);
}
return &(((struct sockaddr_in6*) sa)->sin6_addr);
}
int main(int argc, char *argv[]) {
int sockfd, numbytes;
char buf[MAXDATASIZE];
char buffer[1024];
char *buff;
struct addrinfo hints, *servinfo, *p;
int rv;
char s[INET6_ADDRSTRLEN];
char *port;
int num;
struct timeval tv;
//select data
fd_set rfds;
fd_set wfds;
FD_ZERO(&rfds);
FD_ZERO(&wfds);
if (argc != 2) {
fprintf(stderr, "usage: client port\n");
exit(1);
}
port = argv[1];
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
if ((rv = getaddrinfo("localhost", port, &hints, &servinfo)) != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
return 1;
}
// loop through all the results and connect to the first we can
for (p = servinfo; p != NULL; p = p->ai_next) {
if ((sockfd = socket(p->ai_family, p->ai_socktype,
p->ai_protocol)) == -1) {
perror("client: socket");
continue;
}
if (connect(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
close(sockfd);
perror("client: connect");
continue;
}
break;
}
if (p == NULL) {
fprintf(stderr, "client: failed to connect\n");
return 2;
}
inet_ntop(p->ai_family, get_in_addr((struct sockaddr *) p->ai_addr),
s, sizeof s);
printf("client: connecting to %s\n", s);
freeaddrinfo(servinfo); // all done with this structure
FD_SET(sockfd, &rfds);
FD_SET(sockfd, &wfds);
if (select(sockfd + 1, &rfds, &wfds, NULL, &tv) < 0) {
perror("select");
return -1;
}
if (FD_ISSET(sockfd, &wfds)) {
while (1) {
fgets(buffer, MAXDATASIZE - 1, stdin);
if ((send(sockfd, buffer, strlen(buffer), 0)) == -1) {
fprintf(stderr, "Failure Sending Message\n");
close(sockfd);
exit(1);
} else {
printf("Message being sent: %s\n", buffer);
break;
}
}
}
if (FD_ISSET(sockfd, &rfds)) {
while (1) {
if ((num = recv(sockfd, buffer, 10240, 0)) == -1) {
//fprintf(stderr,"Error in receiving message!!\n");
perror("recv");
exit(1);
} else if (num == 0) {
printf("Connection closed\n");
return 0;
}
// num = recv(client_fd, buffer, sizeof(buffer),0);
buffer[num] = '\0';
printf("Message received: %s\n", buffer);
break;
}
}
close(sockfd);
return 0;
}
server.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <signal.h>
#define BACKLOG 10 // how many pending connections queue will hold
#define MAXDATASIZE 100 // max number of bytes we can get at once
void sigchld_handler(int s) {
while (waitpid(-1, NULL, WNOHANG) > 0);
}
// get sockaddr, IPv4 or IPv6:
void *get_in_addr(struct sockaddr *sa) {
if (sa->sa_family == AF_INET) {
return &(((struct sockaddr_in*) sa)->sin_addr);
}
return &(((struct sockaddr_in6*) sa)->sin6_addr);
}
int main(int argc, char *argv[]) {
int sockfd; // set up socket
int new_sockfd; // new socket after connection
struct addrinfo hints, *results, *p;
struct sockaddr_storage their_addr; // connector's address information
socklen_t sin_size;
struct sigaction sa;
int yes = 1;
char s[INET6_ADDRSTRLEN];
int rv;
int i;
struct timeval tv;
int num;
char buffer[10241];
int nsock;
char buf[MAXDATASIZE];
int numbytes;
char *port;
//select data
fd_set rfds;
fd_set wfds;
FD_ZERO(&rfds);
FD_ZERO(&wfds);
/* validate command-line arguments */
if (argc != 2) {
fprintf(stderr, "Usage: %s port\n", argv[0]);
exit(1);
}
tv.tv_sec = 100;
tv.tv_usec = 0;
/* only argument to port number (./sc [port])*/
port = argv[1];
bzero(&hints, sizeof (struct addrinfo));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE; // any IP
if ((rv = getaddrinfo(NULL, port, &hints, &results)) != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
return 1;
}
// loop through all the results and bind to the first we can
for (p = results; p != NULL; p = p->ai_next) {
if ((sockfd = socket(p->ai_family, p->ai_socktype,
p->ai_protocol)) == -1) {
perror("1: socket");
continue;
}
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes,
sizeof (int)) == -1) {
perror("setsockopt");
exit(1);
}
if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
close(sockfd);
perror("server: bind");
continue;
}
break;
}
if (p == NULL) {
fprintf(stderr, "server: failed to bind\n");
return 2;
}
freeaddrinfo(results); // all done with this structure
if (listen(sockfd, BACKLOG) == -1) {
perror("listen");
exit(1);
}
sa.sa_handler = sigchld_handler; // reap all dead processes
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART;
if (sigaction(SIGCHLD, &sa, NULL) == -1) {
perror("sigaction");
exit(1);
}
printf("server: waiting for connections...\n");
while (1) { // main accept() loop
sin_size = sizeof their_addr;
new_sockfd = accept(sockfd, (struct sockaddr *) &their_addr, &sin_size);
if (new_sockfd == -1) {
perror("accept");
continue;
}
//get the clients info
inet_ntop(their_addr.ss_family,
get_in_addr((struct sockaddr *) &their_addr),
s, sizeof s);
printf("server: got connection from %s\n", s);
FD_SET(new_sockfd, &rfds);
FD_SET(new_sockfd, &wfds);
if (select(new_sockfd + 1, &rfds, &wfds, NULL, &tv) < 0) {
perror("select");
return -1;
}
if (FD_ISSET(new_sockfd, &rfds))
while (1) {
if ((num = recv(new_sockfd, buffer, 10240, 0)) == -1) {
//fprintf(stderr,"Error in receiving message!!\n");
perror("recv");
exit(1);
} else if (num == 0) {
printf("Connection closed\n");
return 0;
}
// num = recv(client_fd, buffer, sizeof(buffer),0);
buffer[num] = '\0';
printf("Message received: %s\n", buffer);
break;
}
if (FD_ISSET(new_sockfd, &wfds))
while (1) {
fgets(buffer, MAXDATASIZE - 1, stdin);
if ((send(new_sockfd, buffer, strlen(buffer), 0)) == -1) {
fprintf(stderr, "Failure Sending Message\n");
close(new_sockfd);
exit(1);
} else {
printf("Message being sent: %s\n", buffer);
break;
}
}
} //Outer While
close(new_sockfd); // parent doesn't need this
return 0;
}
The host and client aren't able to communicate. Can anyone tell me where the issue is?
You need to call select() inside of the loops, not outside. Also, you have to reset the fd_set and timeval structs each time you call select().