【问题标题】:If i want to write multiple requests one by one from client to server, what should I do?如果我想从客户端到服务器一个一个地写入多个请求,我该怎么办?
【发布时间】:2015-12-06 04:35:59
【问题描述】:

例如,一个文件中有几个请求,我读取它们然后使用写入函数逐行发送到服务器。但是,服务器只有一个响应,我无法读取服务器的整个请求。有没有人可以帮助我解决这个问题。非常感谢!

有服务器代码:

    <pre> <code>
    int main(int argc, char *argv[]){
    int sockfd, newsockfd, n;
    unsigned int clientLen;
    char bufferSK[256];
    struct sockaddr_in serv_addr,cli_addr;
    FILE *fp = NULL;

    //create an endpoint for bind, listen and accept.
    sockfd = socket(AF_INET,SOCK_STREAM,0);
    if (sockfd < 0) {
        printf("Failed to create socket for server!\n");
    }
    bzero((char *)&serv_addr, sizeof(serv_addr));

    //set the address of server.
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = INADDR_ANY;
    serv_addr.sin_port = htons(port_number);

    //bind the port with server address
    if (bind(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
        printf("Error on bind!\n");
    }
    listen(sockfd,port_number);
    printf("\nI am listening for connection\n");
    clientLen = sizeof(cli_addr);

    //using accept function to accept the connection from client
    newsockfd = accept(sockfd, (struct sockaddr *)&cli_addr, &clientLen);
    if (newsockfd < 0) {
        printf("Error on accept!\n");
    }
    printf("\nI have accepted your connection\n");
    bzero(bufferSK,256);
    n = read (newsockfd, bufferSK,255);
    if (n < 0) {
        printf("Error reading message from socket\n");
    }

    printf("\nThe message from client is: %s",bufferSK);
    n = write(newsockfd, "SERVER: I got your message!\n", 27);
    if (n < 0) {
        printf("Error writing to socket\n");
    }
    close(newsockfd);
    close(sockfd);
    return 0;
}

有客户端代码:

<pre> <code>

    FILE *fp_queue;

    int main(int argc, char *argv[]){
    int sockfd, server_port_number, n, connectRes;
    struct sockaddr_in serv_addr;
    struct hostent *server;
    char buffer[256];

    //Three parameters must be provided.
    if(argc != 4){
        fprintf(stderr, "Usage: %s server_host_name server_port_number file_path\n",argv[0]);
        exit(0);
    }
    server_port_number = atoi(argv[2]);
    sockfd = socket(AF_INET, SOCK_STREAM, 0);

    //create socket for client.
    if (sockfd < 0) {
        printf("Failed to create socket for client\n");
        exit(0);
    }

    server = gethostbyname(argv[1]);
    if (server == NULL) {
        printf("Oops! There is no such host!\n");
        exit(0);
    }

    //set the attributes of server as zeros.
    bzero((char *)&serv_addr, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    //copy the server address from serv_addr.sin_addr.s_addr to server->h_adddr.
    bcopy((char *)server->h_addr, (char *)&serv_addr.sin_addr.s_addr, server->h_length);

    serv_addr.sin_port = htons(server_port_number);
    connectRes = connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr));
    if (connectRes < 0) {
        printf("Error connection\n");
        exit(0);
    }
    printf("connect successfully\n");
    fp_queue = fopen(argv[3], "r");
    if (fp_queue == NULL) {
        printf("Failed open client file %s\n", argv[3]);
        exit(1);
    }

    bzero(buffer, 256);
    while ((fgets(buffer,sizeof(buffer),fp_queue)) != NULL) {
        buffer[strlen(buffer) - 1] = '\0';
        printf("buffer is %s\n", buffer);
        n = write(sockfd, buffer, strlen(buffer));
        if (n < 0) {
            printf("Error write to socket\n");
        }
        bzero(cliBuffer, 256);
        n = read(sockfd, buffer, 256);
        if (n <0) {
            printf("Error read from socket\n");
        }
        printf("%s\n", buffer);
    }
    close(sockfd);
    return 0;
}

【问题讨论】:

  • 嗨。您介意详细说明您遇到的问题吗?
  • 当然!有一个名为 client.txt 的文件,其中包含 4 个城市的名称。每行一个城市。现在我正在使用 fgets 逐行读取城市名称并编写函数将城市名称从客户端写入服务器端。稍后,我将在服务器端解析城市的特征。但是,我只能将 3 个城市的名称读入服务器端,而服务器只能接收来自客户端的一个请求(城市名称)。因此,我很困惑我应该如何解决这些问题。非常感谢!

标签: c sockets client-server


【解决方案1】:

代码中至少有 2 个设计问题。

服务器代码收到一个请求,发送一个响应,然后服务器终止。如果您想通过一个连接处理更多请求,则服务器代码必须像客户端一样包含一个循环。服务器代码应该包含类似

while ((n = read (newsockfd, bufferSK, 255) > 0) {
    printf("\nThe message from client is: %s",bufferSK);
    n = write(newsockfd, "SERVER: I got your message!\n", 27);
    if (n < 0) {
        printf("Error writing to socket\n");
        break;
    }
}
close(newsockfd);

下一个问题是 TCP 是一个面向流的协议,而您的代码没有考虑到这一点。流方向意味着协议不保留消息边界。当发送者调用write("a"); write("b") 时,接收者可能会在两个单独的读取中获得字符,或者它可能在一次读取中接收到 2 个字符。为了克服这个问题,对等点必须定义一些协议如何确定消息边界。通常客户端在消息的开头发送一个消息长度,或者使用控制字符作为消息边界,或者消息具有固定长度。

【讨论】:

  • 非常感谢,扎博伊。你真的帮了我很多!我已经解决了第一个问题。但是,我仍然对您提到的消息边界感到困惑。 “当发送者调用 write("a"); write("b") 时,接收者可能会在两次单独的读取中获得字符,或者它可能会在一次读取中收到 2 个字符。”我不明白这是什么意思。非常感谢您的帮助!
  • TCP 连接是字节流。这类似于将字节存储到文件中。当应用程序调用write("a"); write("bc") 时,读取器会得到字符串“abc”,并且它无法识别写入器是否进行了一次、两次或三次写入。如果读者第一次读到“a”,第二次读到“bc”,那只是巧合。
  • 知道了!我已经明白问题所在了!我会查找更多材料来解决这个问题!非常感谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多