On running this code I dont see the goodbye printed instead as soon as i enter 'Hello' it terminates with 'Socket operation on non-socket " as error.Also when i send message from client (using localhost ubuntu/multiple consoles) .I can only see messages from second console(client) and upwards but not from the first.And the connection is terminated after the message is displayed else for the case of first client it just waits.
Server code in c
#include <stdio.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#define PORT "3490"
#define STDIN 0
#define STDOUT 1
char *opt;
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;
// master file descriptor list
// temp file descriptor list for select()
// maximum file descriptor number
int listener;
// listening socket descriptor
int newfd;
// newly accept()ed socket descriptor
struct sockaddr_storage remoteaddr; // client address
socklen_t addrlen;
char buf[256];
int nbytes;
// buffer for client data
char remoteIP[INET6_ADDRSTRLEN];
int yes=1;
int i, j, rv;
// for setsockopt() SO_REUSEADDR, below
struct addrinfo hints, *ai, *p;
FD_ZERO(&master);
FD_ZERO(&read_fds);
// clear the master and temp sets
// get us a socket and bind it
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, "selectserver: %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;
}
// lose the pesky "address already in use" error message
setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int));
if (bind(listener, p->ai_addr, p->ai_addrlen) < 0) {
close(listener);
continue;
}
break;
}
// if we got here, it means we didn't get bound
if (p == NULL) {
fprintf(stderr, "selectserver: failed to bind\n");
exit(2);
}
freeaddrinfo(ai); // all done with this
// listen
if (listen(listener, 10) == -1) {
perror("listen");
exit(3);
}
// add the listener to the master set
FD_SET(listener, &master);
FD_SET(STDIN,&master);
// keep track of the biggest file descriptor
fdmax = listener; // so far, it's this one
// main loop
for(;;) {
read_fds = master; // copy it
if (select(fdmax+1, &read_fds, NULL, NULL, NULL) == -1) {
perror("select");
exit(4);
}
// run through the existing connections looking for data to read
for(i = 0; i <= fdmax; i++) {
if (FD_ISSET(i, &read_fds)) { // we got one!!
if (i == listener) {
// handle new connections
addrlen = sizeof remoteaddr;
newfd = accept(listener,
(struct sockaddr *)&remoteaddr,
&addrlen);
if (newfd == -1) {
perror("accept");
} else {
FD_SET(newfd, &master); // add to master set
if (newfd > fdmax) {
// keep track of the max
fdmax = newfd;
}
printf("selectserver: new connection from %s on "
"socket %d\n",inet_ntop(remoteaddr.ss_family,
get_in_addr((struct sockaddr*)&remoteaddr),
remoteIP, INET6_ADDRSTRLEN),
newfd);
}
} else {
// handle data from a client
if ((nbytes = recv(i, buf, sizeof buf, 0)) <= 0) {
// got error or connection closed by client
if (nbytes == 0) {
// connection closed
printf("selectserver: socket %d hung up\n", i);
} else {
perror("recv");
}
close(i); // bye!
FD_CLR(i, &master); // remove from master set
} else {
if(i==STDIN){
printf("Goodbye");
}
// we got some data from a client
for(j = 0; j <= fdmax; j++) {
// send to everyone!
if (FD_ISSET(j, &master)) {
// except the listener and ourselves
if (j != listener && j != i) {
if (send(j, buf, nbytes, 0) == -1) {
perror("send");
}
}
}
}
}
} // END handle data from client
} // END got new incoming connection
} // END looping through file descriptors
} // END for(;;)--and you thought it would never end!
return 0;
}
//New Code modified ,once it takes stdin data by read then it doesnot respond to any other connection probably due to blocking Please help
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <sys/time.h>
#define TRUE 1
#define FALSE 0
//Var
int mode,info;
int PORT;
char *ip_host;
int i,len,rc,on=1;
int listen_sd,max_sd,new_sd;
int desc_ready,end_server=FALSE;
int close_conn;
char buffer[256];
//struct sockaddr_in addr;
struct timeval timeout;
fd_set master_set,working_set;
struct sockaddr_storage remoteaddr; // client addres//s
socklen_t addrlen;
char remoteIP[INET6_ADDRSTRLEN];
char s[INET6_ADDRSTRLEN];
struct addrinfo hints, *loadinfo, *ptr;
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 servcl_memset(){
memset(&hints, 0, sizeof(hints));
hints.ai_family= AF_UNSPEC;
hints.ai_socktype= SOCK_STREAM;
}
void cl_connect()
{
for(ptr = loadinfo; ptr != NULL; ptr = ptr->ai_next) {
if ((listen_sd = socket(ptr->ai_family, ptr->ai_socktype,ptr->ai_protocol)) == -1) {
perror("client: socket");
continue;
}
if (connect(listen_sd, ptr->ai_addr, ptr->ai_addrlen) == -1) {
close(listen_sd);
perror("client: connect");
continue;
}
break;
}
if (ptr == NULL) {
fprintf(stderr, "client: failed to connect(bind)\n");
exit(0);
}
inet_ntop(ptr->ai_family, get_in_addr((struct sockaddr *)ptr->ai_addr),s, sizeof s);
printf("client: connecting to %s\n", s);
freeaddrinfo(loadinfo); // all done with this structure
}
void init_socket(){
for(ptr = loadinfo; ptr != NULL; ptr = ptr->ai_next) {
if ((listen_sd = socket(ptr->ai_family, ptr->ai_socktype,ptr->ai_protocol)) == -1) {
perror("server: socket");
continue;
}
rc = setsockopt(listen_sd, SOL_SOCKET, SO_REUSEADDR,(char *)&on, sizeof(on));
if (rc < 0)
{
perror("setsockopt() failed");
close(listen_sd);
continue;
}
rc = bind(listen_sd,ptr->ai_addr,ptr->ai_addrlen);
if (rc < 0)
{
perror("bind() failed");
close(listen_sd);
continue;
}
break;
}//End For
if (ptr == NULL) {
fprintf(stderr, "client/server: failed to connect(bind)\n");
exit(0);
}
freeaddrinfo(loadinfo); // all done with this structure
}
void unblock(){
rc = ioctl(listen_sd, FIONBIO, (char *)&on);
if (rc < 0)
{
perror("ioctl() failed");
close(listen_sd);
exit(-1);
}
}
void sock_listen(){
rc = listen(listen_sd, 32);
if (rc < 0)
{
perror("listen() failed");
close(listen_sd);
exit(-1);
}
/*************************************************************/
/* Initialize the master fd_set
*/
/*************************************************************/
FD_ZERO(&master_set);
max_sd = listen_sd;
FD_SET(0,&master_set);
FD_SET(listen_sd, &master_set);
}
void conn_timeout(){
timeout.tv_sec = 3 * 60;
timeout.tv_usec = 0;
}
/*void client_listen(){
do
{
memcpy(&working_set, &master_set, sizeof(master_set));
printf("Waiting on select()...\n");
rc = select(max_sd + 1, &working_set, NULL, NULL, &timeout);
if (rc < 0)
{
perror(" select() failed");
break;
}
if (rc == 0)
{
printf(" select() timed out. End program.\n");
break;
}
desc_ready = rc;
*/
void start_listen(){
do
{
memcpy(&working_set, &master_set, sizeof(master_set));
printf("Waiting on select()...\n");
rc = select(max_sd + 1, &working_set, NULL, NULL, &timeout);
if (rc < 0)
{
perror(" select() failed");
break;
}
if (rc == 0)
{
printf(" select() timed out. End program.\n");
break;
}
desc_ready = rc;
for (i=0; i <= max_sd && desc_ready > 0; ++i)
{
if (FD_ISSET(i, &working_set))
{
desc_ready -= 1;
if (i == listen_sd)
{
printf(" Listening socket is readable\n");
do
{
addrlen = sizeof remoteaddr;
new_sd = accept(listen_sd, (struct sockaddr *)&remoteaddr,&addrlen);
if (new_sd < 0)
{
if (errno != EWOULDBLOCK)
{
perror(" accept() failed");
end_server = TRUE;
}
break;
}
printf(" New incoming connection - %d\n", new_sd);
printf("selectserver: new connection from %s on "
"socket %d\n",
inet_ntop(remoteaddr.ss_family,
get_in_addr((struct sockaddr*)&remoteaddr),
remoteIP, INET6_ADDRSTRLEN),
new_sd);
FD_SET(new_sd, &master_set);
if (new_sd > max_sd)
max_sd = new_sd;
} while (new_sd != -1);
}
else
{
printf(" Descriptor %d is readable\n", i);
close_conn = FALSE;
//do
//{
rc = read(i, buffer, sizeof(buffer)-1);
if (rc < 0)
{
if (errno != EWOULDBLOCK)
{
perror(" recv() failed");
close_conn = TRUE;
}
break;
}
if (rc == 0)
{
printf(" Connection closed\n");
close_conn = TRUE;
break;
}
len = rc;
printf(" %d bytes received\n", len);
if (i==0)i=1;
rc = write(i, buffer, len);
if (i==1)i=0;
if (rc < 0)
{
perror(" send() failed");
close_conn = TRUE;
break;
}
//} while (TRUE);
if (close_conn)
{
close(i);
FD_CLR(i, &master_set);
if (i == max_sd)
{
while (FD_ISSET(max_sd, &master_set) == FALSE)
max_sd -= 1;
}
}
} /* End of existing connection is readable */
} /* End of if (FD_ISSET(i, &working_set)) */
} /* End of loop through selectable descriptors */
end_server==TRUE;} while (end_server == FALSE);
}
void conn_close(){
for (i=0; i <= max_sd; ++i)
{
if (FD_ISSET(i, &master_set))
close(i);
}
}
void cl_socket() {
printf("Please enter the message: ");
do
{
memcpy(&working_set, &master_set, sizeof(master_set));
printf("Waiting on select()...\n");
rc = select(max_sd + 1, &working_set, NULL, NULL,NULL);
if (rc < 0)
{
perror(" select() failed");
break;
}
desc_ready = rc;
for (i=0; i <= max_sd && desc_ready > 0; ++i)
{
if (FD_ISSET(i, &working_set))
{
desc_ready -= 1;
printf(" Descriptor %d is readable\n", i);
close_conn = FALSE;
do
{
fgets(buffer,255,stdin);
rc = write(listen_sd, buffer,strlen(buffer));
if (rc < 0)
{
perror(" send() failed");
close_conn = TRUE;
}
rc = read(listen_sd, buffer, sizeof(buffer)-1);
if (rc < 0)
{
if (errno != EWOULDBLOCK)
{
perror(" recv() failed");
close_conn = TRUE;
}
}
if (rc == 0)
{
printf(" Connection closed\n");
close_conn = TRUE;
}
len = rc;
printf(" %d bytes received\n", len);
} while (TRUE);
if (close_conn)
{
close(i);
FD_CLR(i, &master_set);
if (i == max_sd)
{
while (FD_ISSET(max_sd, &master_set) == FALSE)
max_sd -= 1;
}
}
}//Working set
}//For loop
end_server==TRUE;} while (end_server == FALSE);
}
main(int argc,char * argv[])
{
mode=atoi(argv[1]);
PORT=atoi(argv[2]);
ip_host=(argv[3]);
servcl_memset();
if (mode ==1){
printf("In client mode\n");
if ((info = getaddrinfo(argv[3], argv[2], &hints, &loadinfo)) != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(info));
return 1;
}
cl_connect();
unblock();
conn_timeout();
cl_socket();
conn_close();
}
else {
printf("In server mode\n");
hints.ai_flags=AI_PASSIVE;
if ((info = getaddrinfo(NULL, argv[2], &hints, &loadinfo)) != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(info));
return 1;
}
init_socket();
unblock();
sock_listen();
conn_timeout();
start_listen();
conn_close();
}
}
/*
*/
I also have another client that i am using for testing.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
void error(const char *msg)
{
perror(msg);
exit(0);
}
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]);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket");
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);
if (connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0)
error("ERROR connecting");
printf("Please enter the message: ");
bzero(buffer,256);
fgets(buffer,255,stdin);
n = write(sockfd,buffer,strlen(buffer));
if (n < 0)
error("ERROR writing to socket");
bzero(buffer,256);
n = read(sockfd,buffer,255);
if (n < 0)
error("ERROR reading from socket");
printf("%s\n",buffer);
close(sockfd);
return 0;
}
This is actually a linux problem, because you're trying to use recv
and send
to read from and write to STDIN (which is probably a terminal not a socket). Unlike most UNIX variants, in Linux, send
and recv
can only be used on sockets, not on any file descriptor. For a terminal, you need to use read
and write
.
There's also the issue that it's weird to write to STDIN -- normally you only read from STDIN and write to STDOUT. But as long as STDIN is somethine like a terminal you can write to, it would be ok.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.