简体   繁体   中英

Abrupt termination of server (Socket operation on non-socket)

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM