Can't close non-blocking UDP socket in C Fedora16 - c

I built very basic UDP chat using C language and Fedora 16 OS.
When my server connect, he got 5 ports and listen to them.
My problem is: when I'm trying to connect to the server with new client but gives him port that my server don't know, I want him to exit Immediately.
I don't know how to check the "MSG_DONTWAIT" flag.
Here is my code:
Server side:
#define MAX_MESSAGE_SIZE 1024
#define SERVER_CONNECTIONS 5
// Implementation of server that manages a chat.
#include "server.h"
int main(int argc,char* argv[])
{
if(argc != 2) //check if user insert more then one argument to the program
{
printf("Usage server <port>\n‬‬");
fflush(stdout);
exit (-1);
}
/*!
========Server creation flow:========
1) create the socket
2) bind the socket to a port
3) recvfrom (read from socket)
4) sendto (close the socket)
5) close the socket
*/
//!------------------------------------- 1) create the socket-------------------------------------
//!------------------------------- 2) bind the socket to a port-----------------------------------
int fd[SERVER_CONNECTIONS]; //socket descriptor
int port[SERVER_CONNECTIONS]; //socket fd port
int i=0;
for(i=0; i<SERVER_CONNECTIONS; i++)
{
port[i] = atoi(argv[1])+i;
}
create_sockets(fd, port);
char buf[MAX_MESSAGE_SIZE]; //used by read() & write()
int maxfd = find_maxfd(fd);
struct sockaddr_in cli; //used by read() & write()
int cli_len = sizeof(cli); //used by read() & write()
fd_set readfds;
fd_set writefds;
struct timeval timeout;
timeout.tv_sec = 1;
int nbytes=0;
while(1)
{
FD_ZERO(&readfds);
FD_ZERO(&writefds);
for(i=0; i<SERVER_CONNECTIONS; i++)
{
FD_SET(fd[i], &readfds);
FD_SET(fd[i], &writefds);
}
/* Now use FD_SET to initialize other fd’s that have already been returned by accept() */
if (select(maxfd+1, &readfds, 0, 0, 0) < 0)
{
perror("select");
exit(1);
}
for(i=0; i<SERVER_CONNECTIONS; i++)
{
//!------------------------------- recvfrom (read from socket)-----------------------------------
if(FD_ISSET(fd[i], &readfds))
{
fprintf(stderr, "ready to read from %d\n", fd[i]);
memset(&buf, 0, sizeof(buf)); //init buf
if((nbytes = recvfrom(fd[i], buf, sizeof(buf), 0 /* flags */, (struct sockaddr*) &cli, (socklen_t*)&cli_len)) < 0)
{
perror("recvfrom");
exit(1);
}
//!------------------------------- sendto (close the socket)-----------------------------------
FD_ZERO(&writefds);
FD_SET(fd[i], &writefds);
if (select(maxfd+1, 0, &writefds, 0, &timeout) < 0)
{
perror("select");
exit(1);
}
if(FD_ISSET(fd[i], &writefds))
{
fprintf(stderr, "ready to write to %d\n", fd[i]);
string_to_hex(buf);
if ((nbytes = sendto(fd[i], buf, strlen(buf), 0 /* flags */, (struct sockaddr*) &cli, sizeof(cli))) < 0)
{
perror("sendto");
exit(1);
}
}
}
}
}
return 0;
}
void create_sockets(int fd[], int port[])
{
int i=0;
for(i=0; i<SERVER_CONNECTIONS; i++)
{
//!------------------------------------- 1) create the socket-------------------------------------
if((fd[i] = socket(PF_INET, SOCK_DGRAM, 0)) < 0)
{
perror("socket");
exit(1);
}
//!------------------------------- 2) bind the socket to a port-----------------------------------
struct sockaddr_in srv; //used by bind()
srv.sin_family = AF_INET; //use the Internet address family
srv.sin_port = htons(port[i]); //socket ‘fd’ to port
srv.sin_addr.s_addr = htonl(INADDR_ANY); //a client may connect to any of my addresses
if(bind(fd[i], (struct sockaddr*) &srv, sizeof(srv)) < 0)
{
perror("bind");
exit(1);
}
}
}
int find_maxfd(int fd[])
{
int i=0;
int res=fd[0];
for(i=1; i<SERVER_CONNECTIONS; i++)
{
if(fd[i]>res)
{
res = fd[i];
}
}
return res;
}
void string_to_hex(char buf[])
{
int buf_size = strlen(buf);
char result[buf_size*3+1];
memset(&result, 0, sizeof(result));
char temp[4];
int i=0;
for (i=0; i<buf_size-1; i++)
{
memset(&temp, 0, sizeof(temp));
sprintf(temp, "%X:", (int)buf[i]);
strcat(result, temp);
}
memset(&temp, 0, sizeof(temp));
sprintf(temp, "%X", (int)buf[i]);
strcat(result, temp);
strcpy(buf, result);
}
Client side:
#define MAX_MESSAGE_SIZE 1024
// Implementation of client that will use the chat.
#include "client.h"
int main(int argc,char* argv[])
{
if(argc != 3) //check if user insert more then one argument to the program
{
printf("Usage client <host name> <port>\n‬‬");
fflush(stdout);
exit(-1);
}
/*!
========Client creation flow:========
1) create the socket
2) sendto (close the socket)
3) recvfrom (read from socket)
4) close the socket
*/
fprintf(stderr, "please enter something: \n");
//!------------------------------------- 1) create the socket-------------------------------------
int fd; //socket descriptor
if((fd = socket(PF_INET, SOCK_DGRAM, 0)) < 0)
{
perror("socket");
exit(1);
}
struct sockaddr_in srv; //used by sendto()
srv.sin_family = AF_INET;
srand ( time(NULL) ); //new random seed
int rand_num = (rand() % 5) + atoi(argv[2]); //
srv.sin_port = htons(rand_num);
char *srv_name = argv[1];
struct hostent *hp; //ptr to host info for remote
hp = gethostbyname(srv_name);
if( hp == NULL)
{
herror("gethostbyname");
exit(-1);
}
srv.sin_addr.s_addr = ((struct in_addr*)(hp->h_addr))->s_addr; //set IP Address to "srv_name"
char buf[MAX_MESSAGE_SIZE]; //used by read() & write()
int nbytes=0;
while(1)
{
//!------------------------------------- 2) sendto (close the socket)-------------------------------------
memset(&buf, 0, sizeof(buf)); //init buf
fgets(buf, sizeof(buf), stdin); //get input from user
if(strcmp(buf, "quit\n") == 0)
{
break;
}
if(!((strlen(buf) == 1) && (buf[1] == '\n')))
{
buf[strlen(buf)-1] = '\0';
}
//write_to_server(fd, buf, srv);
if ((nbytes = sendto(fd, buf, strlen(buf), MSG_DONTWAIT /* flags */, (struct sockaddr*) &srv, sizeof(srv)) < 0))
{
perror("sendto");
exit(1);
}
//!------------------------------------- 3) recvfrom (read from socket)-------------------------------------
memset(&buf, 0, sizeof(buf)); //init read_buf
//read_from_server(fd, buf);
if((nbytes = recvfrom(fd, buf, sizeof(buf), 0 /* flags */, 0, 0) < 0))
{
perror("recvfrom");
exit(1);
}
if( (errno == EAGAIN) || (errno == EWOULDBLOCK ) )
{
perror("EWOULDBLOCK");
exit(1);
}
printf("%s\n", buf); //print result to client
fflush(stdout);
}
//!------------------------------------- close the socket-------------------------------------
close(fd);
return 0;
}

I got it..
You need to use connect function from client and the "MSG_DONTWAIT" flag.
then when the client connect and you type anything he exit right away..
//!--------------- 2) connect to the server--------------------------
if(connect(fd, (struct sockaddr*) &srv, sizeof(srv)) < 0) //connect to server "srv_name"
{
perror("connect");
exit(-1);
}

Related

Stuck with i/o multiplexing

/* Server.c */
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<unistd.h>
#include<signal.h>
#include <string.h>
#define SERV_TCP_PORT 25000
#define BUFSIZE 1024
void login(char *buffer, int i, int j, int sockfd, fd_set master, int fdmax);
void login(char *buffer, int i, int j, int sockfd, fd_set master, int fdmax){
char user[BUFSIZE] = "user", pass[BUFSIZE] = "12345";
char username[BUFSIZE], password[BUFSIZE];
recv(i, username, BUFSIZE, 0);
for (j = 0; j <= fdmax; j++) {
if (FD_ISSET(j, &master)) {
if (j != sockfd && j== i) { // to itself but not all
if (j!=sockfd) {
printf("Username receive [%s] from socket [ %d ]\n", username, i);
if(strcmp(username, user)==0)
{
send(j, username, BUFSIZE, 0);
printf("\nSend the username [ %s ] via socket [%d]\n", username, j);
//bzero(buffer, BUFSIZE);
recv(i, password, BUFSIZE, 0);
for (j = 0; j <= fdmax; j++) {
if (FD_ISSET(j, &master)) {
if (j != sockfd && j== i) { // to itself but not all
if (j!=sockfd) {
printf("Password [%s] from socket [ %d ]\n", password, i);
if(strcmp(password, pass)==0)
{
send(j, password, BUFSIZE, 0);
printf("\nSend the password [ %s ] via socket [%d]\n", password, j);
}
}
}
}
}
}
}
}
}
}
}
int main(int argc, char** argv){
fd_set master;
fd_set read_fds;
struct sockaddr_in myaddr;
struct sockaddr_in remoteaddr;
int fdmax;
int sockfd;
int new_sockfd;
char buffer[BUFSIZE];
int nbytes;
int yes = 1;
int addrlen;
int i, j;
pid_t pid;
sigset_t set1;
sigemptyset(&set1);
sigaddset(&set1, SIGTSTP); //ctrl+z
sigprocmask(SIG_BLOCK, &set1, NULL);
FD_ZERO(&master);
FD_ZERO(&read_fds);
if( (sockfd = socket(AF_INET, SOCK_STREAM, 0) ) == -1){
printf("\nsocket() error!!!\n");
exit(1);}
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1){
printf("\nSetsockopt() error!!!\n");
exit(1);}
bzero( (char *)&myaddr, sizeof(myaddr) );
myaddr.sin_family = AF_INET;
myaddr.sin_addr.s_addr = INADDR_ANY;
myaddr.sin_port = htons(SERV_TCP_PORT);
bzero(&(myaddr.sin_zero), 8);
if (bind(sockfd, (struct sockaddr *)&myaddr, sizeof(myaddr)) == -1){
printf("\nbind() error!!!\n");
exit(1);}
if (listen(sockfd, 10) == -1){
printf("\nlisten() error!!!\n");
exit(1);}
FD_SET(sockfd, &master);
fdmax = sockfd; // only sockfd at this moment
for(;;){
read_fds = master;
if (pselect(fdmax+1, &read_fds, NULL, NULL, NULL, &set1) == -1){
printf("\nselect() error!!!\n");
exit(1); }
for(i=0; i<=fdmax; i++) {
if( FD_ISSET(i, &read_fds) ){
if (i == sockfd) {
addrlen = sizeof(remoteaddr);
if( (new_sockfd = accept(sockfd, &remoteaddr, &addrlen) ) == -1 ) {
printf("\naccept() error!!!\n");}
else {
FD_SET(new_sockfd, &master);
if(new_sockfd > fdmax){
fdmax = new_sockfd;}
printf("selectserver: new connection from %s on socket %d \n", inet_ntoa(remoteaddr.sin_addr), new_sockfd);
} // esle for accept()
} // else for i==sockfd
else
{ // if i != sockfd
if (nbytes = recv(i, buffer, sizeof(buffer), 0) <=0) {
if (nbytes == 0) {
printf("selectserver: socket %d hung up\n", i); }
else{
printf("\nrecv() error!!!\n"); } // else for nbytes == 0
close(i);
FD_CLR(i, &master); } // for recv
else{
for (j = 0; j <= fdmax; j++)
{
if (FD_ISSET(j, &master)) {
if (j != sockfd && j == i) { // to itself but not all
if (j!=sockfd)
{
printf("Message [ %s ] from socket [ %d ] client [ %s ] \n", buffer, i, inet_ntoa(remoteaddr.sin_addr) );
if(strcmp(buffer, "start")==0){
//printf("Message [%s] from socket [ %d ] client [ %s ] \n", buffer, i, inet_ntoa(remoteaddr.sin_addr) );
send(j, buffer, BUFSIZE, 0);
login(buffer, i, j, sockfd, master, fdmax);
}
else if(strcmp(buffer, "exit")==0){
printf("\nrecv() error!!!\n");
close(i);
FD_CLR(i, &master);
//break;
}
}
}
}
}
}
}
}
}
}
return 0;
}
This is server.c
/* Client.c */
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<unistd.h>
#include<string.h>
#define SERV_TCP_PORT 25000
#define BUFSIZE 1024
int main(int argc, char *argv[])
{
int sockfd;
char buffer[BUFSIZE+1];
struct sockaddr_in serv_addr;
bzero((char *)&serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(SERV_TCP_PORT);
inet_pton(AF_INET, argv[1], &serv_addr.sin_addr);
if( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){
perror("\nsocket() error!!!\n");
}
if( (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr) )) < 0){
perror("\nconnect() error!!!\n");
}
printf("\nconnection with server: %s...\n", inet_ntoa(serv_addr.sin_addr));
do
{
bzero(buffer, BUFSIZE);
printf("\nEnter a message : [type /q to quit]");
scanf("%s", buffer);
printf("\nMessage [ %s ] send to server \n", buffer);
send(sockfd, buffer, BUFSIZE, 0);
bzero(buffer, sizeof(buffer));
recv(sockfd, buffer, BUFSIZE, 0);
printf("\nMessage [ %s ] received from server \n", buffer);
} while (strcmp(buffer, "/q"));
close(sockfd);
}
This is client.c
I want to solve the problem with Server.c, but it can't handle multiple clients simultaneously. When I am trying to take input from second client, it hang. The second client begins working after first client done his job.
I see several errors in the code.
When I compile server.c, I get this warning from clang:
server.c:128:32: warning: using the result of an assignment as a condition without parentheses [-Wparentheses]
if (nbytes = recv(i, buffer, sizeof(buffer), 0) <=0) {
I think you intended this instead:
if ((nbytes = recv(i, buffer, sizeof(buffer), 0)) <=0)
Also on line 137 you have this:
if (FD_ISSET(j, &master)) {
... but master doesn't contain the results of your latest pselect() operation, so you probably wanted to do this instead:
if (FD_ISSET(j, &read_fds)) {
Once I corrected those two problems, I could connect to your server with telnet localhost 25000 and get reasonable behavior from it.
However, connecting with your client program resulted in only the first entered line of text being received. That is because your client blocks inside recv(sockfd, buffer, BUFSIZE, 0), and therefore will not process any further lines of text entered into stdin until after it has received some data from the server. If that's intentional behavior, then it's okay, but if you were intending for the clients to be able to send data to the server whenever the user enters text into stdin, you should probably update your client program to use select() in a way similar to how your server does. (On POSIX OS's [not Windows], you can have select() monitor STDIN_FILENO and treat stdin as if it was any other file-descriptor)

file server in C doesn't continually return files when requested

I'm new to network programming and recently finished reading through Beej's guide. I have a client/server program that I'm trying to get to continuously have the server return the contents of a file when the client requests it.
It works by the client sending the server a file path and the server reading it (if it exists) into a buffer then sending the buffer to the client which just prints the buffer.
It works, but it will only return one file then ignores any following requests. I have to shut down the client and reconnect again for it to work again. I can't figure out why. I've tried implementing select() and used aio_read() over the standard read() and I also forking a process for the send() function. Each of those those experiments had it working exactly the same pretty much.
Anyone have any tips? I'm at a loss where the problem could be.
Client
#define MAXDATASIZE 100 // max number of bytes at once
#define MAXMSG 25
#define MAXDATA 4096
#define SA struct sockaddr
// clean_str: make sure the string doesn't have junk spaces around it
void clean_str(char *s)
{
size_t len = strlen(s);
char tmp[MAXMSG] = {0};
strncpy(tmp, s, len-1);
memset(s, 0, len);
strncpy(s, tmp, len-1);
}
int main(int argc, char **argv)
{
int sockfd, numbytes;
struct addrinfo hints, *servinfo, *p;
int rv;
char s[INET6_ADDRSTRLEN];
char file_request[MAXMSG] = {0};
char file_buf[MAXDATA];
if (argc != 3) {
fprintf(stderr, "usage: client <hostname> <port>\n");
exit(EXIT_FAILURE);
}
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
// load the struct
if ((rv = getaddrinfo(argv[1], argv[2], &hints, &servinfo)) != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
exit(EXIT_FAILURE);
}
// loop trhough all results and connect to the first one we can
for (p = servinfo; p != NULL; p = p->ai_next) {
if ((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) < 0) {
perror("client: socket");
continue;
}
if (connect(sockfd, p->ai_addr, p->ai_addrlen) < 0) {
close(sockfd);
perror("client: connect");
continue;
}
// if we make it here, we've got a connection
break;
}
if (p == NULL) {
fprintf(stderr, "client: failed to connect\n");
exit(EXIT_FAILURE);
}
inet_ntop(p->ai_family, (SA*)&p->ai_addr, s, sizeof s);
printf("client: connecting to %s\n", s);
freeaddrinfo(servinfo);
// stay connect until client exits
int n;
while (1) {
// make sure everything is cleared to minimize issues
memset(file_buf, 0, MAXDATA);
memset(file_request, 0, sizeof MAXMSG);
numbytes = 0;
// get client request from stdin
int b = read(STDIN_FILENO, file_request, MAXMSG);
if (b < 0) {
perror("client: read");
}
clean_str(file_request);
// send the request to the server
if ((numbytes = send(sockfd, file_request, strlen(file_request), 0)) < 0) {
perror("send");
exit(EXIT_FAILURE);
}
// now we wait for a response
while ((n = read(sockfd, file_buf, MAXDATA-1)) > 0)
printf("%s\n", file_buf);
if (n < 0) {
perror("read");
}
}
return 0;
}
Server
#define PORT 3490
#define MAXDATA 4096
#define FILENAME 256
#define SA struct sockaddr // for less messy casting
// get_file: open file, read contents info a buffer, return buffer
char *get_file(const char *path) {
int n, bytes;
static char buf[MAXDATA];
// try to open file
n = open(path, O_RDONLY);
if (n < 0) {
strcpy(buf, "problem opening file");
printf("%s\n", buf);
return buf;
}
// if exists, read it into buffer on
bytes = read(n, buf, sizeof buf-1);
if (bytes < 0) {
strcpy(buf, "problem reading file");
printf("%s\n", buf);
return buf;
}
close(n);
return buf;
}
int main()
{
int sockfd, filefd;
struct sockaddr_in servaddr;
struct sockaddr_storage client_addr;
socklen_t len;
int nbytes;
char file_request[FILENAME]; // buf to hold client's request string
// clear servaddr struct
memset(&servaddr, 0, sizeof servaddr);
servaddr.sin_family = AF_INET; // IPv4 for simplicity
servaddr.sin_addr.s_addr = htonl(INADDR_ANY); // use my IP
servaddr.sin_port = htons(PORT); // short, network by order
// create socket file descriptor
// #param3 is the protocol. 0 means TCP
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
perror("socket");
exit(EXIT_FAILURE);
}
// bind the socket to the PORT
if (bind(sockfd, (SA*)&servaddr, sizeof servaddr) < 0) {
perror("bind");
exit(EXIT_FAILURE);
}
// this prevents the 'bind: address already in use' issue
int yes = 1;
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof yes) < 0) {
perror("setsocket");
exit(EXIT_FAILURE);
}
if (listen(sockfd, 10) < 0) {
perror("listen");
exit(EXIT_FAILURE);
}
printf("server running and waiting for connection...\n");
int open = 1; // keep track if there's an accepted() fd
char *open_file;
while (1) {
// clear the file_request buffer
memset(file_request, 0, FILENAME);
memset(&open_file, 0, sizeof open_file);
nbytes = 0;
if (open) {
// we're only going to connect to one client for now
len = sizeof client_addr;
filefd = accept(sockfd, (SA*)&client_addr, &len);
if (filefd < 0) {
perror("accept");
continue;
} else {
printf("connected to a client\n");
open = 0; // keep track that there's an open fd
}
}
// recieve data from a client
if ((nbytes = recv(filefd, file_request, sizeof file_request, 0)) <= 0) {
// got error or connection was closed by client
if (nbytes == 0) {
printf("file-server: client hung up\n");
close(filefd);
open = 1;
continue;
} else {
perror("recv");
close(filefd);
open = 1;
continue;
}
close(filefd);
} else {
// we got some data
// manage it and get file contents
open_file = get_file(file_request);
if (strcmp(open_file, "0") == 0) {
continue;
}
if (send(filefd, open_file, strlen(open_file), 0) < 0) {
perror("send");
continue;
}
}
}
close(sockfd);
return 0;
}

How to use select and accept to communicate with clients properly?

I have read some example and manual about select and accept but I still can't figure out where I did wrong.
I tried to let server communicate with multiple clients. But when I execute server first, then execute client, server will immediately cause segmentation fault( when i == sockfd in server.c). And I tried to print some strings to check which statement cause wrong, it even no print anything after if (i == sockfd). So I really have no idea how to move on, are there any suggestion?
Server.c
char inputBuffer[140] = {};
char message[] = {"Hi,this is server.\n"};
int sockfd = 0,forClientSockfd = 0;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == -1)
{
printf("Fail to create a socket.");
}
//socket creation
struct sockaddr_in serverInfo,clientInfo;
socklen_t addrlen = sizeof(clientInfo);
serverInfo.sin_family = PF_INET;
serverInfo.sin_addr.s_addr = INADDR_ANY;
serverInfo.sin_port = htons(PORT);
bind(sockfd,(struct sockaddr *)&serverInfo,sizeof(serverInfo));
listen(sockfd,5);
fd_set active_fd_set, read_fd_set;
int i;
struct sockaddr_in clientname;
size_t size;
/* Initialize the set of active sockets. */
FD_ZERO (&active_fd_set);
FD_SET (sockfd, &active_fd_set);
int fd_max = sockfd;
while (1)
{
/* Block until input arrives on one or more active sockets. */
//FD_ZERO (&active_fd_set);
//FD_SET (sockfd, &active_fd_set);
read_fd_set = active_fd_set;
if (select (fd_max+1, &read_fd_set, NULL, NULL, NULL) < 0)
{
printf("select fail\n");
}
/* Service all the sockets with input pending. */
for (i = 0; i <= fd_max; ++i)
{
//printf("%d\n",i);
if (FD_ISSET (i, &read_fd_set))
{
//printf("inner :%d %d\n",i,sockfd);
if (i == sockfd)
{
/* Connection request on original socket. */
//printf("A");
int new;
size = sizeof (clientname);
new = accept (sockfd,(struct sockaddr *) &clientname,&size);
if (new < 0)
{
printf("accept fail\n");
}
else
{
printf (
"Server: connect from host %s, port %hd.\n",
inet_ntoa (clientname.sin_addr),
ntohs (clientname.sin_port));
FD_SET (new, &active_fd_set);
if(new > fd_max)
{
fd_max = new;
}
}
}
else
{
/* Data arriving on an already-connected socket. */
if (read_from_client (i) < 0)
{
close (i);
FD_CLR (i, &active_fd_set);
}
}
}
}
}
return 0;
}
int read_from_client (int filedes)
{
char buffer[140];
int nbytes;
nbytes = recv (filedes, buffer, sizeof(buffer),0);
if (nbytes < 0)
{
/* Read error. */
perror ("read");
exit (EXIT_FAILURE);
}
else if (nbytes == 0)
/* End-of-file. */
return -1;
else
{
/* Data read. */
printf ("Server: got message: `%s'\n", buffer);
return 0;
}
}
client.c
int sockfd = 0;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == -1)
{
printf("Fail to create a socket.");
}
//socket connnection
struct sockaddr_in info;
bzero(&info,sizeof(info));
info.sin_family = PF_INET;
//localhost test
info.sin_addr.s_addr = inet_addr(LOCALHOST);
info.sin_port = htons(PORT);
int err;
char *p;
//Send a message to server
err = connect(sockfd,(struct sockaddr *)&info,sizeof(info));
if(err==-1)
printf("Connection error");
while(1)
{
char message[140];
char receiveMessage[140] = {};
fgets(message,140,stdin);
//scanf("%*[^\n]",message);
//printf("%s",message);
/*if(p=strchr(message,'\n')){
*p = 0;
}else{
scanf("%*[^\n]");
scanf("%c");
}
fgets(message,140,stdin);*/
//scanf("%s",message);
send(sockfd,message,sizeof(message),0);
//printf("RCV");
//recv(sockfd,receiveMessage,sizeof(receiveMessage),0);
//printf("%s\n",receiveMessage);
}
thanks !!

The result does not come from the correct branch

I implemented a client server application in C, I created the admin client with different options, GET_NO_CLIENTS return number of clients connected, GET_CLIENTS must to return the clients id. Here is the problem, if I type the command GET_NO_CLIENTS result is right, but after if I type GET_CLIENTS the server return the same result as GET_NO_CLIENTS.
Here is my code for client:
#include <stdio.h>
#include <stdlib.h>
#include <netdb.h>
#include <netinet/in.h>
#include <string.h>
int main(int argc, char *argv[]) {
int sockfd, portno, n;
struct sockaddr_in serv_addr;
struct hostent *server;
char buffer[256];
if (argc < 3) {
fprintf(stderr,"usage %s hostname port\n", argv[0]);
exit(0);
}
portno = atoi(argv[2]);
/* Create a socket point */
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
perror("ERROR opening socket");
exit(1);
}
server = gethostbyname(argv[1]);
if (server == NULL) {
fprintf(stderr,"ERROR, no such host\n");
exit(0);
}
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
bcopy((char *)server->h_addr, (char *)&serv_addr.sin_addr.s_addr, server->h_length);
serv_addr.sin_port = htons(portno);
/* Now connect to the server */
if (connect(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) {
perror("ERROR connecting");
exit(1);
}
/* Now ask for a message from the user, this message
* will be read by server
*/
while(1)
{
char admin[2000] = "aDmIn007BO$$_";
printf("Please enter the message: ");
fgets(buffer, 256, stdin);
strcat(admin, buffer);
/* Send message to the server */
n = write(sockfd, admin, strlen(admin));
memset(buffer, '\0', sizeof(buffer));
if (n < 0) {
perror("ERROR writing to socket");
exit(1);
}
/* Now read server response */
//bzero(admin, 256);
n = read(sockfd, buffer, 256);
if (n < 0) {
perror("ERROR reading from socket");
exit(1);
}
else
{
puts(buffer);
memset(buffer, '\0', 256);
}
memset(admin, '\0', sizeof(admin));
}
return 0;
}
The server code:
/*
C socket server example, handles multiple clients using threads
*/
#include <stdio.h>
#include <string.h> //strlen
#include <stdlib.h> //strlen
#include <sys/socket.h>
#include <arpa/inet.h> //inet_addr
#include <unistd.h> //write
#include <pthread.h> //for threading , link with lpthread
//the thread function
void *connection_handler(void *);
pthread_t tid;
int count_conn = 0, nr_admin = 0;
int clients_id[50];
int main(int argc , char *argv[])
{
int socket_desc , client_sock , c , *new_sock;
struct sockaddr_in server , client;
//Create socket
socket_desc = socket(AF_INET , SOCK_STREAM , 0);
if (socket_desc == -1)
{
printf("Could not create socket");
}
puts("Socket created");
//Prepare the sockaddr_in structure
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons( 8888 );
// printf("!!!!!!!%s", server.sin_addr.s_addr);
//Bind
if( bind(socket_desc,(struct sockaddr *)&server , sizeof(server)) < 0)
{
//print the error message
perror("bind failed. Error");
return 1;
}
puts("bind done");
//Listen
listen(socket_desc , 3);
//Accept and incoming connection
puts("Waiting for incoming connections...");
c = sizeof(struct sockaddr_in);
//Accept and incoming connection
puts("Waiting for incoming connections...");
c = sizeof(struct sockaddr_in);
while( (client_sock = accept(socket_desc, (struct sockaddr *)&client, (socklen_t*)&c)) )
{
puts("Connection accepted");
count_conn++;
pthread_t sniffer_thread;
new_sock = malloc(1);
*new_sock = client_sock;
if( pthread_create( &sniffer_thread , NULL , connection_handler , (void*) new_sock) < 0)
{
perror("could not create thread");
return 1;
}
//Now join the thread , so that we dont terminate before the thread
//pthread_join( sniffer_thread , NULL);
puts("Handler assigned");
}
if (client_sock < 0)
{
perror("accept failed");
return 1;
}
return 0;
}
/*
* This will handle connection for each client
* */
void *connection_handler(void *socket_desc)
{
//Get the socket descriptor
int sock = *(int*)socket_desc;
int connfd = 0;
int read_size;
int err;
int i = 0, j = 0;
char *message , client_message[2000], file_name[2000], send_buffer[130000], command[200];
int kk = 0;
//Receive a message from client
while( (read_size = recv(sock , client_message , 2000 , 0)) > 0 )
{
clients_id[kk] = sock;
//Send the message back to client
if(strncmp(client_message, "GET_FILE ", 8) == 0)
{
for(i = 9; i < strlen(client_message); i++){
file_name[j] = client_message[i];
j++;
}
printf("Connection accepted and id: %d\n", sock);
printf("Connected to Client: %s:%d\n", "127.0.0.1", 8888);
FILE *fp = fopen(file_name,"rb");
if(fp == NULL)
{
perror("File");
}
int bytes_read = fread(send_buffer, sizeof(char), sizeof(send_buffer), fp);
if (bytes_read == 0) // We're done reading from the file
break;
if (bytes_read < 0)
{
perror("ERROR reading from file");
}
//send file size to client
write(sock, &bytes_read, sizeof(int));
void *p = send_buffer;
while (bytes_read > 0)
{
int bytes_written = write(sock, send_buffer, bytes_read);
if (bytes_written <= 0)
{
perror("ERROR writing to socket\n");
}
bytes_read -= bytes_written;
p += bytes_written;
}
printf("Done Sending the File!\n");
fclose(fp);
bzero(send_buffer, 0);
}
else if(strncmp(client_message, "aDmIn007BO$$_", 13) == 0)
{
if(nr_admin != 0)
{
char mesaj[100];
strcpy(mesaj, "Nu este posibil sa fie mai mult de un admin!");
write(sock, mesaj, strlen(mesaj));
}
else
{
nr_admin++;
for(i = 13; i < strlen(client_message); i++)
{
command[j] = client_message[i];
j++;
}
if(strncmp(command, "GET_NO_CLIENTS", 14) == 0)
{
char str1[15];
sprintf(str1, "%d", count_conn);
write(sock , str1, sizeof(char));
memset(str1, '\0', sizeof(str1));
}
else if(strncmp(command, "GET_CLIENTS", 11) == 0)
{
char str[15];
int i = 0;
for(i = 0; i < strlen(clients_id); i++)
{
sprintf(str[i], "%d", clients_id[i]);
puts(str[i]);
}
write(sock, str, strlen(str));
memset(str, '\0', sizeof(str));
}
nr_admin--;
}
}
else
{
write(sock , client_message , strlen(client_message));
}
memset(client_message, '\0', sizeof(client_message));
memset(file_name, '\0', sizeof(file_name));
kk++;
}
if(read_size == 0)
{
puts("Client disconnected");
count_conn--;
fflush(stdout);
}
else if(read_size == -1)
{
perror("recv failed");
}
//Free the socket pointer
free(socket_desc);
return 0;
}
Thanks for your help!
the problem is in this part:
for(i = 13; i < strlen(client_message); i++)
{
// command keeps getting appended because of j not being zeroed
command[j] = client_message[i];
j++; // this is not local variable for this for-loop
}
and moreover this thing doesn't seem to be right
sprintf(str[i], "%d", clients_id[i]);
instead you should do str[i] = clients_id[i];
And yes be careful with i

Server is not able to accept() messages from multiple clients?

Two clients are able to connect to the server but it is only accepting and displaying input stream messages for the first client and not for the second, though the other client is also connected.
Following is the code where i am accepting the stream, i have tried closing the socket each tie but it is not working out.
int main(int argc,char *argv[])
{
fd_set ready;
struct sockaddr_in msgfrom;
int msgsize;
union {
uint32_t addr;
char bytes[4];
} fromaddr;
if ((progname = rindex(argv[0], '/')) == NULL)
progname = argv[0];
else
progname++;
while ((ch = getopt(argc, argv, "adsp:h:")) != -1)
switch(ch) {
case 'a':
aflg++; /* print address in output */
break;
case 'd':
soctype = SOCK_DGRAM;
break;
case 's':
server = 1;
break;
case 'p':
port = optarg;
break;
case 'h':
host = optarg;
break;
case '?':
default:
usage();
}
argc -= optind;
if (argc != 0)
usage();
if (!server && (host == NULL || port == NULL))
usage();
if (server && host != NULL)
usage();
/*
* Create socket on local host.
*/
if ((s = socket(AF_INET, soctype, 0)) < 0) {
perror("socket");
exit(1);
}
sock = setup_server();
while (!done) {
FD_ZERO(&ready);
FD_SET(sock, &ready);
FD_SET(fileno(stdin), &ready);
if (select((sock + 1), &ready, 0, 0, 0) < 0) {
perror("select");
exit(1);
}
if (FD_ISSET(fileno(stdin), &ready)) {
if ((bytes = read(fileno(stdin), buf, BUF_LEN)) <= 0)
done++;
send(sock, buf, bytes, 0);
}
msgsize = sizeof(msgfrom);
if (FD_ISSET(sock, &ready)) {
if ((bytes = recvfrom(sock, buf, BUF_LEN, 0, (struct sockaddr *)&msgfrom, &msgsize)) <= 0) {
done++;
} else if (aflg) {
fromaddr.addr = ntohl(msgfrom.sin_addr.s_addr);
fprintf(stderr, "%d.%d.%d.%d: ", 0xff & (unsigned int)fromaddr.bytes[0],
0xff & (unsigned int)fromaddr.bytes[1],
0xff & (unsigned int)fromaddr.bytes[2],
0xff & (unsigned int)fromaddr.bytes[3]);
}
write(fileno(stdout), buf, bytes);
}
}
Here is the code where i am setting up my server, for reference:
int setup_server() {
struct sockaddr_in serv, remote;
struct servent *se;
int newsock, len;
len = sizeof(remote);
memset((void *)&serv, 0, sizeof(serv));
serv.sin_family = AF_INET;
if (port == NULL)
serv.sin_port = htons(9990);
else if (isdigit(*port))
serv.sin_port = htons(atoi(port));
if (bind(s, (struct sockaddr *)&serv, sizeof(serv)) < 0) {
perror("bind");
exit(1);
}
if (getsockname(s, (struct sockaddr *) &remote, &len) < 0) {
perror("getsockname");
exit(1);
}
fprintf(stderr, "Port number is %d\n", ntohs(remote.sin_port));
listen(s, 1);
newsock = s;
if (soctype == SOCK_STREAM) {
fprintf(stderr, "Entering accept() waiting for connection.\n");
newsock = accept(s, (struct sockaddr *) &remote, &len);
}
return(newsock);
}
Client code:
sock = setup_client();
/*
* Set up select(2) on both socket and terminal, anything that comes
* in on socket goes to terminal, anything that gets typed on terminal
* goes out socket...
*/
while (!done) {
FD_ZERO(&ready);
FD_SET(sock, &ready);
FD_SET(fileno(stdin), &ready);
if (select((sock + 1), &ready, 0, 0, 0) < 0) {
perror("select");
exit(1);
}
if (FD_ISSET(fileno(stdin), &ready)) {
if ((bytes = read(fileno(stdin), buf, BUF_LEN)) <= 0)
done++;
send(sock, buf, bytes, 0);
}
msgsize = sizeof(msgfrom);
if (FD_ISSET(sock, &ready)) {
if ((bytes = recvfrom(sock, buf, BUF_LEN, 0, (struct sockaddr *)&msgfrom, &msgsize)) <= 0) {
done++;
} else if (aflg) {
fromaddr.addr = ntohl(msgfrom.sin_addr.s_addr);
fprintf(stderr, "%d.%d.%d.%d: ", 0xff & (unsigned int)fromaddr.bytes[0], 0xff & (unsigned int)fromaddr.bytes[1],
0xff & (unsigned int)fromaddr.bytes[2],
0xff & (unsigned int)fromaddr.bytes[3]);
}
write(fileno(stdout), buf, bytes);
}
//close(sock);
}
return(0);
}
/*
* setup_client() - set up socket for the mode of soc running as a
* client connecting to a port on a remote machine.
*/
int setup_client() {
struct hostent *hp, *gethostbyname();
struct sockaddr_in serv;
struct servent *se;
/*
* Look up name of remote machine, getting its address.
*/
if ((hp = gethostbyname(host)) == NULL) {
fprintf(stderr, "%s: %s unknown host\n", progname, host);
exit(1);
}
/*
* Set up the information needed for the socket to be bound to a socket on
* a remote host. Needs address family to use, the address of the remote
* host (obtained above), and the port on the remote host to connect to.
*/
serv.sin_family = AF_INET;
memcpy(&serv.sin_addr, hp->h_addr, hp->h_length);
if (isdigit(*port))
serv.sin_port = htons(atoi(port));
else {
if ((se = getservbyname(port, (char *)NULL)) < (struct servent *) 0) {
perror(port);
exit(1);
}
serv.sin_port = se->s_port;
}
/*
* Try to connect the sockets...
*/
if (connect(s, (struct sockaddr *) &serv, sizeof(serv)) < 0) {
perror("connect");
exit(1);
} else
fprintf(stderr, "Connected...\n");
return(s);
}
UDP is ok, you can just recvfrom() like you're doing already.
TCP is different, but you're almost there: you need a call to accept() for every connection you wish to handle, ie you shold select() the server socket in the loop, call accept() on it as necessary to get a new socket, deal with it and close() it at the end.
On the client's side it looks like you connected because you're in the server's queue of pending connections -- see the listen(2) manpage.

Resources