2013-01-18 131 views
0

我使用C語言和Fedora 16 OS構建了非常基本的UDP聊天。無法關閉C中的非阻塞UDP套接字Fedora16

當我的服務器連接時,他有5個端口,並聽取他們的意見。

我的問題是:當我試圖用新客戶端連接到服務器,但給他的端口,我的服務器不知道,我希望他立即退出。

我不知道如何檢查「MSG_DONTWAIT」標誌。

這裏是我的代碼:

服務器端:

#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); 
} 

客戶端:

#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; 
} 
+3

UDP不連接。如果客戶使用了錯誤的端口號,他們只會在黑暗中大喊大叫。 – wildplasser

+0

當我試圖用新客戶端連接到服務器,但給他的端口,我的服務器不知道「是什麼意思?如果你需要固定端口,爲什麼不在綁定時間修復它們? – EJP

回答

0

我得到了它..

您需要使用連接功能客戶端和「MSG_DONTWAIT」標誌。

那麼當客戶端連接,並鍵入什麼,他立刻退出..

//!--------------- 2) connect to the server-------------------------- 
if(connect(fd, (struct sockaddr*) &srv, sizeof(srv)) < 0) //connect to server "srv_name" 
{ 
    perror("connect"); 
    exit(-1); 
}