2017-04-25 64 views
1

今天我的问题是关于套接字编程。我正在开发一个创建客户端和服务器的程序,客户端通过给定的命令与服务器数据库中的记录进行交互。我对套接字编程非常陌生,并且我已经给出了一些入门代码来让服务器和客户端连接并进行交互。这就是说,我很不熟悉上述代码的哪一部分需要迭代,以便接收和发送另一条消息,直到发出“停止”命令。在此之前,我希望用户能够继续发送消息到服务器。用套接字程序接受顺序用户输入

(相关的)服务器代码:

void error(char *msg) 
{ 
    perror(msg); 
    exit(1); 
}  
int main() { 
    int num = 1; 
    int del; 
    int sockfd, newsockfd, portno; 
    socklen_t clilen; 
    char buffer[256]; 
    struct sockaddr_in serv_addr, cli_addr; 
    int n; 


    /*STEP 1*********************************************/ 

    sockfd = socket(AF_INET, SOCK_STREAM, 0); 

    /*Make sure opening was successful*/ 
    if (sockfd < 0) 
     error("ERROR opening socket"); 

    /*STEP 2******************************************** 
     0 out the server address*/ 

    memset((char *) &serv_addr, 0, sizeof(serv_addr)); 

    /*convert argument to int*/ 
    portno = PORTNO; 

    /*this is always the same for this type of connection*/ 
    serv_addr.sin_family = AF_INET; 

    /*INADDR_ANY is a macro that will find the current machine IP*/   
    serv_addr.sin_addr.s_addr = INADDR_ANY; 

    /*make sure byte order is correct 
     may be a no-op, but better safe than sorry*/ 
    serv_addr.sin_port = htons(portno); 



    /*STEP 3********************************************/ 
    if (bind(sockfd, (struct sockaddr *) &serv_addr, 
       sizeof(serv_addr)) < 0) { 
     error("ERROR on binding"); 
    } 



    /*STEP 4******************************************** 
        Open server up for listening, if you don't listen 
        you won't hear*/ 

    listen(sockfd,5); 


    /*STEP 5******************************************/ 

    clilen = sizeof(cli_addr); 

    /*Accept blocks until a connection with 
     a client is made. Returns a new socket 
     to communicate with the new connection. 
     Also receives address data about client*/ 



    /*Communicate************************************/ 

    char *array[20]; 
    do { 
     newsockfd = accept(sockfd, 
       (struct sockaddr *) &cli_addr, 
       &clilen); 

     if (newsockfd < 0) 
      error("ERROR on accept"); 

     memset(buffer, 0, 256); 

     printf("%s", "Enter Message:"); 
     n = read(newsockfd,buffer,255); 
     printf("I read %d\n",n); 

     if (n < 0) error("ERROR reading from socket"); 
     printf("Here is the message: %s",buffer); 

     n = write(newsockfd,"I got your message",18); 
     if (n < 0) error("ERROR writing to socket"); 

     int i = 0; 
     char *p = strtok(buffer, " "); 

     while (p != NULL) 
     { 
      array[i++] = p; 
      p = strtok (NULL, " "); 
     } 
     if (strcmp(array[0], "put") == 0) { 
      insert(&front, array); 
      puts("PUT COMMAND"); 
     } else if (strcmp(array[0], "get") == 0 && strcmp(array[1], "lname") == 0) { 
      puts("GET LNAME COMMAND"); 
     } else if (strcmp(array[0], "get") == 0 && strcmp(array[1], "fname") == 0) { 
      puts("GET FNAME COMMAND"); 
     } else if (strcmp(array[0], "get") == 0 && strcmp(array[1], "SID") == 0) { 
      puts("GET SID COMMAND"); 
     } else if (strcmp(array[0], "get") == 0 && strcmp(array[1], "GPA") == 0) { 
      puts("GET GPA COMMAND"); 
     } else if (strcmp(array[0], "delete") == 0 && strcmp(array[1], "SID") == 0) { 
      puts("DELETE COMMAND"); 
     } else { 
      printf("%s\n", "Not a valid command."); 
     } 
    } while (strcmp(array[0], "stop") != 0); 

    return 0; 
} 

(相关)的客户端代码:

#define PORTNO 20321 
#include <stdio.h> 
#include <stdlib.h> 
#include <sys/types.h> 
#include <string.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <netdb.h> 
#include <unistd.h> 


void error(char *msg) 
{ 
      perror(msg); 
       exit(0); 
} 

int main(int argc, char *argv[]) 
{ 
    /*set up ints for socket file descriptor 
     port number and return of read/write*/ 
    int sockfd, portno, n; 
    int i; 

    /*structure for server info*/ 
    struct sockaddr_in serv_addr; 

    /*used to hold the return of the function 
     that finds our server address, will 
     be copied into serv_addr*/ 
    struct hostent *server; 


    /*for our message*/ 
    char buffer[256]; 

    /*make sure usage is correct*/ 
    if (argc < 2) { 
     fprintf(stderr,"usage %s hostname\n", argv[0]); 
     exit(0); 
    } 

    /*convert our port number*/ 
    portno = PORTNO; 

    /*create the socket*/ 
    sockfd = socket(AF_INET, SOCK_STREAM, 0); 

    /*make sure it was made*/ 
    if (sockfd < 0) 
     error("ERROR opening socket"); 

    /*gethostbyname takes our host domain name and 
     resolves it to an address, there is a similar 
     function, gethostbyaddr that takes an address 
     and returns the same struct, struct hostent*/ 
    server = gethostbyname(argv[1]); 

    /*make sure the host exists*/ 
    if (server == NULL) { 
     fprintf(stderr,"ERROR, no such host\n"); 
     exit(0); 
    } 

    /*0 out the server address stuct and set members*/ 
    memset((char *) &serv_addr, 0, sizeof(serv_addr)); 
    serv_addr.sin_family = AF_INET; 

    /*copy the data returned from gethostbyname 
     into the server address struct*/ 
    memcpy((char *)server->h_addr_list, 
      (char *)&serv_addr.sin_addr.s_addr, 
      server->h_length); 
    serv_addr.sin_port = htons(portno); 

    /*Request a connection to the server through the socket we set up 
     make sure it connected, this function will also do the binding 
     of our socket and server info*/ 
    if (connect(sockfd,(struct sockaddr*) &serv_addr,sizeof(serv_addr)) < 0) { 
     error("ERROR connecting"); 
    } 

    for (i = 0; i < 3; i++) { 
     printf("Choose an operation: \n 1. put ln,fn,mi,SID,GPA\n 2. get lname\n 3. get fname\n 4. get SID\n 5. get GPA\n 6. delete (SID)\n 7. stop\nChoice: "); 
     /*Retrieve a message to send from the user*/ 

     memset(buffer, 0, 256); 
     fgets(buffer,255,stdin); 

     /*send the message to the socket*/ 
     printf("length is %d\n", (int)strlen(buffer)); 
     n = write(sockfd,buffer,strlen(buffer)); 
     if (n < 0) 
      error("ERROR writing to socket"); 
     memset(buffer, 0, 256); 

     /*await an incoming message, read stops all process*/ 
     n = read(sockfd,buffer,255); 
     if (n < 0) 
      error("ERROR reading from socket"); 
     printf("%s\n",buffer); 
     return 0; 
    } 
} 

我的服务器似乎是正确的等待消息,我可以重新启动我的客户端程序和发送另一个消息,而服务器正在等待,并像往常一样接收。但它的方式,它会要求另一个消息,但它不会像第一个那样得到正确的发送/接收。现在,我已经把它设置为循环3次,只是作为一个测试。如何正确地创建这个读/写循环到服务器?

回答

0

假设你只想一次只有一个连接,那么这个未经测试的while循环版本应该可以工作。

while (true) 
{ 
    newsockfd = accept(sockfd, 
      (struct sockaddr *) &cli_addr, 
      &clilen); 

    if (newsockfd < 0) 
     error("ERROR on accept"); 

    while (true) 
    { 
     memset(buffer, 0, 256); 

     printf("%s", "Enter Message:"); 
     n = read(newsockfd,buffer,255); 
     printf("I read %d\n",n); 

     if (n < 0) error("ERROR reading from socket"); 
     printf("Here is the message: %s",buffer); 

     n = write(newsockfd,"I got your message",18); 
     if (n < 0) error("ERROR writing to socket"); 

     int i = 0; 
     char *p = strtok(buffer, " "); 

     while (p != NULL) 
     { 
      array[i++] = p; 
      p = strtok (NULL, " "); 
     } 
     if (strcmp(array[0], "put") == 0) { 
      insert(&front, array); 
      puts("PUT COMMAND"); 
     } else if (strcmp(array[0], "get") == 0 && strcmp(array[1], "lname") == 0) { 
      puts("GET LNAME COMMAND"); 
     } else if (strcmp(array[0], "get") == 0 && strcmp(array[1], "fname") == 0) { 
      puts("GET FNAME COMMAND"); 
     } else if (strcmp(array[0], "get") == 0 && strcmp(array[1], "SID") == 0) { 
      puts("GET SID COMMAND"); 
     } else if (strcmp(array[0], "get") == 0 && strcmp(array[1], "GPA") == 0) { 
      puts("GET GPA COMMAND"); 
     } else if (strcmp(array[0], "delete") == 0 && strcmp(array[1], "SID") == 0) { 
      puts("DELETE COMMAND"); 
     } 
     // Checking for stop command here 
     else if (strcmp(array[0], "stop") ==0) 
     { 
      close(newsockfd); 
      break; 
     } 
     else { 
      printf("%s\n", "Not a valid command."); 
     } 
    } 
}