3

我对套接字编程非常陌生,并且遇到了麻烦。我想实现一个根据特定客户端请求进行响应的服务器。就我而言,GET、HEAD 或其他错误。考虑以下代码

如果我在调用之前打印答案send()(请参阅下面的服务器端代码),则消息是正确的。但是让我们从我发送的客户说

  1. 得到
  2. 得到
  3. 测试
  4. 得到

,从客户端打印的答案是

You want GET
You want HEAD
You want GETD
HTTP/1.1 400 Bad Request
You want GET Bad Request

所以看起来从服务器发送的消息有点“覆盖”,但这是如何避免的呢?如果这是问题所在,是否可以“清除服务器缓冲区”?

这是完整的服务器端代码

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>

#define BUFSIZE         1024
#define MAXPENDING      100

int main(){

    char get[] = "GET";
    char head[] = "HEAD";
    int serverSocket = socket(PF_INET, SOCK_STREAM, 0);

    struct sockaddr_in serverAddress;
    serverAddress.sin_family = AF_INET;
    serverAddress.sin_port = htons(8080);
    serverAddress.sin_addr.s_addr = htonl(INADDR_ANY);
    memset(&serverAddress.sin_zero, '\0', 8);

    bind(serverSocket, (struct sockaddr*)&serverAddress, sizeof(serverAddress));

    listen(serverSocket, MAXPENDING);

    for(;;){
        struct sockaddr_in clientAddress;
        int clientAddressLength = sizeof(clientAddress);
        int clientSocket;

        clientSocket = accept(serverSocket, (struct sockaddr*)&clientAddress, &clientAddressLength);

        char buf[BUFSIZE];
        int bytesRec;

        bytesRec = recv(clientSocket, buf, BUFSIZE, 0);
        while(bytesRec > 0){

            char *result;
            result = strtok(buf, " ");

            printf("result %s\n", result);

            if(strcmp(&buf, &get) == 0){
                char answer[] = "You want GET";
                send(clientSocket, answer, strlen(answer), 0);
            }else{
                if(strcmp(&buf, &head) == 0){
                    char answer[] = "You want HEAD";
                    send(clientSocket, answer, strlen(answer), 0);
                }else{
                    char answer[] = "HTTP/1.1 400 Bad Request";
                    send(clientSocket, answer, strlen(answer), 0); 
                }
            }

            bytesRec = recv(clientSocket, buf, BUFSIZE, 0);
        }

    return 0;
}

和客户端

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>

int main(){

    int clientSocket = socket(PF_INET, SOCK_STREAM, 0);

    struct sockaddr_in clientAddress;
    clientAddress.sin_family = AF_INET;
    clientAddress.sin_port = 0;
    clientAddress.sin_addr.s_addr = htonl(INADDR_ANY);
    memset(&clientAddress.sin_zero, '\0', 8/*sizeof(clientAddress.sin_zero)*/);

    bind(clientSocket, (struct sockaddr*)&clientAddress, sizeof(clientAddress));

    struct sockaddr_in serverAddress;
    serverAddress.sin_family = AF_INET;
    serverAddress.sin_port = htons(8080);
    serverAddress.sin_addr.s_addr = inet_addr("127.0.0.1");
    memset(&serverAddress.sin_zero, '\0', 8);

    if(connect(clientSocket, (struct sockaddr*)&serverAddress, sizeof(serverAddress)) == -1){
        printf("error in connecting!\n");
        return 0;
    }

    char* serverReply[1024];

    for(;;){
        char request[100];
        printf("Enter your request: ");
        scanf("%s", &request);
        send(clientSocket, request, strlen(msg), 0);
        if(recv(clientSocket, serverReply, strlen(serverReply), 0) < 0){
            printf("failure in receiving from server!\n");
        }else{
            printf("%s\n", serverReply);
        }
    }

    close(clientSocket);

    return 0;
}
4

2 回答 2

5
send(clientSocket, request, strlen(msg), 0);

这仅发送字符串字符,不包括终止 NULL。接收缓冲区不会终止服务器端接收到的字符串。

这就是为什么您仍然看到上一条消息中的“D”字符的原因。

You want GETD <-- 'D' is from the previous 'HEAD'

要么终止服务器上接收到的字符串,

buf[bytesRec] = '\0';

编辑:正如@Zan 指出的,不要这样做:

或从客户端发送 NULL 终止符。

send(clientSocket, request, strlen(msg) + 1, 0);

于 2013-04-01T16:49:21.967 回答
2

如果你strcmp()错了

(1)我可以从你的问题中理解,而不是你需要比较的buf result,喜欢:(你在评论中说结果打印为GET)

if(strcmp(result, get) == 0){

(2)正如@phihag 回答的那样,应该是

if(strcmp(buf, get) == 0){
          ^   ^remove &

您在每个 strcmp() 上都有类似的错误,因为buf, get,head都是宪章数组。

(3) recv()不会终止读取缓冲区,因此最好\0在使用它之前添加 null ()(我可以注意到您正在使用 buff 作为字符串

喜欢:

bytesRec = recv(clientSocket, buf, BUFSIZE, 0);
buf[bytesRec] = '\0'

感染你应该只读取BUFSIZE-1剩下的一个字节作为空'\0'符号,例如:

ytesRec = recv(clientSocket, buf, BUFSIZE-1, 0);
buf[bytesRec] = '\0' 
于 2013-04-01T16:48:18.093 回答