linux 中的套接字 TCP - 客户端无法插入用户名

Socket TCP in linux - Client cannot insert username

我在使用 TCP/IP 套接字实现 signin/signup 系统时遇到了麻烦。

所以,每当我要用户注册时,客户端不能输入用户名,但他可以输入密码。好像跳过了一步

这是代码。

客户端

void func(int sockfd)
{
    char username[MAX], password[MAX];
    int n, c;

    bzero(username, sizeof(username));
    printf("Enter the username : ");
    n = 0;
    while ((username[n++] = getchar()) != '\n')
        ;
    write(sockfd, username, sizeof(username));
    bzero(username, sizeof(username));

    bzero(password, sizeof(password));
    printf("Enter the password : ");
    c = 0;
    while ((password[c++] = getchar()) != '\n')
        ;
    write(sockfd, password, sizeof(password));
    bzero(username, sizeof(password));
}

...

int choice, ans;
    
func(sockfd);

bzero(buffer, 255);
n = read(sockfd, buffer, 255);
if(n < 0)
    error("Error reading from socket");
printf("Server - %s", buffer);
scanf("%d", &choice);
write(sockfd, &choice, sizeof(int));
    
if(choice == 1) {
    func(sockfd);
}


if(choice == 3) {
    printf("Session terminated\n");
    close(sockfd);
}

close(sockfd);
return 0;

服务器

void func(int newsockfd)
{
    char username[MAX], password[MAX];
    int n;

    bzero(username, MAX);
    read(newsockfd, username, sizeof(username));
    printf("From client: %s\n", username);

    bzero(password, MAX);
    read(newsockfd, password, sizeof(password));
    printf("From client pass: %s\n", password);

    while ((username[n++] = getchar()) != '\n')
        ;

    write(newsockfd, username, sizeof(username));
}

int main(int argc, char *argv[]) {


    func(newsockfd);

    int num1, num2, ans, choice;

    n = write(newsockfd, "Benvenuto, inserisci una scelta: \n1. Registrazione\n2. Login\n3. Esci\n", strlen("Benvenuto, inserisci una scelta: \n1. Registrazione\n2. Login\n3. Esci\n"));
    if(n < 0) error("Error writing to socket");
    read(newsockfd, &choice, sizeof(int));

    switch(choice) {
        case 1:
            func(newsockfd);
            break;
        
        case 2:
            break;

        case 3:
            close(newsockfd);
            close(sockfd);
    }
    
    close(newsockfd);
    close(sockfd);
    return 0;
}

这是一个例子:

a) 你可以 printf("choice: %d\n", choice);
b) 我无法查看套接字是否被您的第一个函数调用阻塞
c) 最重要的是 - 我们必须关注一个事实,即您尝试发送序列化数据 (int) - 这与发送纯文本完全不同。搜索 google:“网络字​​节顺序”:

 //client 
 uint32_t choice;
 choice = htons(choice);
 write(sockfd, &choice, sizeof(choice));

//server
uint32_t choice;
read(newsockfd, &choice, sizeof(uint32_t));
choice = ntohs(choice);

switch(choice);

忽略提供的代码不是完整代码这一事实,客户端和服务器甚至不使用相同的协议,所以您当然会 运行 遇到问题。

客户端甚至在收到服务器的初始提示之前就将用户名和密码发送到服务器。

服务器期望客户端的第一个输入是用户对提示的选择,但客户端首先发送用户名,因此服务器收到的前几个字符将被误解为整数。

当服务器确实希望收到用户名和密码时,它会发回用户名,而客户端不会读取。

您还完全忽略了 read()write() 的 return 值。而且您也没有正确处理接收到的字符串。

话虽如此,请尝试更类似的方法:

共享

int sendAll(int sockfd, void *buf, size_t len)
{
    char *pbuf = (char*) buf;
    int n;

    while (len > 0) {
        n = send(sockfd, pbuf, len, 0);
        if (n < 0) return n;
        pbuf += n;
        len -= n;
    }

    return 0;
}

int recvAll(int sockfd, void *buf, size_t len)
{
    char *pbuf = (char*) buf;
    int n;

    while (len > 0) {
        n = recv(sockfd, pbuf, len, 0);
        if (n <= 0) return n;
        pbuf += n;
        len -= n;
    }

    return 1;
}

int sendInt32(int sockfd, int32_t value)
{
    value = htonl(value);
    return sendAll(sockfd, &value, sizeof(value));
}

int recvInt32(int sockfd, int32_t *value)
{
    int n = recvAll(sockfd, value, sizeof(*value));
    if (n == 1) *value = ntohl(*value);
    return n;
}

int sendStr(int sockfd, const char *str)
{
    int len = strlen(str);
    int n = sendInt32(sockfd, len);
    if (n == 0) n = sendAll(sockfd, str, len);
    return n;
}

int recvStr(int sockfd, char **str)
{
    *str = NULL;

    int32_t len;
    int n = recvInt32(sockfd, &len);
    if (n <= 0) return n;

    *str = malloc(len + 1);
    if (*str == NULL) return -1;

    n = recvAll(sockfd, *str, len);
    if (n <= 0) {
        free(*str);
        *str = NULL;
        return n;
    }

    (*str)[len] = '[=10=]';
    return 1;
}

客户端

void func(int sockfd)
{
    char input[MAX+1];
    int n, c;

    printf("Enter the username : ");
    n = 0;
    while ((n < MAX) && ((c = getchar()) != EOF) && (c != '\n')) {
        input[n++] = (char) c;
    }
    input[n] = '[=11=]';

    if (sendStr(sockfd, input) < 0)
        error("Error writing to socket");

    printf("Enter the password : ");
    n = 0;
    while ((n < MAX) && ((c = getchar()) != EOF) && (c != '\n')) {
        input[n++] = (char) c;
    }
    input[n] = '[=11=]';

    if (sendStr(sockfd, input) < 0)
        error("Error writing to socket");

    char *ans;
    if (recvStr(sockfd, &ans) <= 0)
        error("Error reading from socket");

    printf("Server - %s: ", ans);
    free(ans);
}

int main() {
    int sockfd, choice;
    char *str;
    
    // connect to server...
    sockfd = ...;

    if (recvStr(sockfd, &str) <= 0)
        error("Error reading from socket");

    printf("Server - %s", str);
    free(str);

    scanf("%d", &choice);

    if (sendInt32(sockfd, choice) < 0)
        error("Error writing to socket");
    
    switch (choice) {
        case 1:
        case 2:
            func(sockfd);
            break;

        case 3:
            printf("Session terminated\n");
            break;
    }

    close(sockfd);
    return 0;
}

服务器

void func(int sockfd, int choice)
{
    char *input;

    if (recvStr(sockfd, &input) <= 0)
        error("Error reading from socket");

    printf("From client user: %s\n", input);
    free(input);

    if (recvStr(sockfd, &input) <= 0)
        error("Error reading from socket");

    printf("From client pass: %s\n", input);
    free(input);

    char *ans = (choice == 1) ? "Registered" : "Logged in";
    if (sendStr(sockfd, ans) < 0)
        error("Error writing to socket");
}

int main() {

    int sockfd, clientsockfd, n;
    int32_t choice;

    // setup listening socket ...
    sockfd = ...;

    // accept client ...
    clientsockfd = ...;

    if (SendStr(clientsockfd, "Benvenuto, inserisci una scelta: \n1. Registrazione\n2. Login\n3. Esci\n") < 0)
        error("Error writing to socket");

    if (recvInt32(clientsockfd, &choice) < 0)
        error("Error reading from socket");

    switch (choice) {
        case 1:
        case 2:
            func(clientsockfd, choice);
            break;

        case 3:
            close(clientsockfd);
            break;
    }
    
    close(sockfd);
    return 0;
}