使用套接字程序

时间:2017-04-25 01:13:35

标签: c sockets

我今天的问题是关于套接字编程。我正在开发一个创建客户端和服务器的程序,客户端通过给定的命令与服务器数据库中的记录进行交互。我是套接字编程的新手,我已经获得了一些启动代码,以使服务器和客户端连接并进行交互。话虽这么说,我非常不熟悉所述代码的哪一部分需要迭代才能接收和发送另一条消息,直到给出“停止”命令。在那之前,我希望用户能够继续向服务器发送消息。

(相关)服务器代码:

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次作为测试。如何正确地为服务器创建此读/写循环?

1 个答案:

答案 0 :(得分: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.");
        }
    }
}