C++ UNIX 帮助 - 简单的 TCP 服务器套接字连接

Posted

技术标签:

【中文标题】C++ UNIX 帮助 - 简单的 TCP 服务器套接字连接【英文标题】:C++ UNIX Help - simple TCP server socket connection 【发布时间】:2022-01-07 15:36:30 【问题描述】:

我是一名学生,使用 UNIX 系统调用编写 C++ 代码,以执行来自终端的简单服务器 客户端请求。用户(我)在终端中输入两个程序(服务器和客户端)的端口以建立连接,目标是服务器将客户端程序输入的内容发送回客户端。

即:

1 号航站楼: ./server 9000

2 号航站楼: ./client localhost 9000 ~

将显示 Home 中所有目录和文件的列表。

或者 终端2:./client localhost 9000 test.txt

将从 test.txt 文件中读取内容并将其写入客户端的终端。

到目前为止,只有文件夹有效。每当我尝试使用文件时,它都会打印一个空行。这是我的流程功能代码:

void processClientRequest(int connSock)

    int received;
    char path[1024], buffer[1024];
    
    // Read from the client
    if((received = read(connSock, path, sizeof(path))) < 0)
     perror("receive"); exit(EXIT_FAILURE); 
    
    // Check if it is a directory or a file
        struct stat s;
        if(stat(path,&s) == 0 )
        
            // It is a directory
            if(s.st_mode & S_IFDIR)
            
                DIR *dirp = opendir(path);
                if (dirp == 0)
                
                    // Tell client they gave the inappropriate input
                    // Duplicate socket descriptor into error output
                    // Then print it to client's end with perror to
                    // Give more in-depth details of the error to user
                    close(2);
                    dup(connSock);
                    perror(path);
                    exit(EXIT_SUCCESS);
                
            
                struct dirent *dirEntry;
                while((dirEntry = readdir(dirp)) != NULL)
                
                    // If statement to hides all files/folders that start with a dot
                    // Which are hidden files/folders
                    if(dirEntry->d_name[0] != '.')
                    
                        strcpy(buffer, dirEntry->d_name);
                        strcat(buffer, "\n");
                        if(write(connSock, buffer, strlen(buffer)) < 0)
                         perror("write"); exit(EXIT_FAILURE); 
                    
                
                closedir(dirp);
                close(connSock);
                exit(EXIT_SUCCESS);         
            
            // It is a file
            else if(s.st_mode & S_IFREG)
            
                int fd = open(path, O_RDONLY);
                if(fd < 0)  perror("open"); exit(EXIT_FAILURE); 
                read(fd, buffer, strlen(buffer));
                strcat(buffer, "\n");
                if(write(connSock, buffer, strlen(buffer)) < 0)
                 perror("write"); exit(EXIT_FAILURE); 
                close(fd);
            
            // Not a file or directory
            else
            
                cout << "It is neither a file nor directory!" << endl;
                exit(EXIT_FAILURE);
            
        
    
        else
        
            // Same explanation as line 95 - 98
            close(2);
            dup(connSock);
            perror("stat");
            exit(EXIT_SUCCESS);
        
    close(connSock);
    exit(EXIT_SUCCESS);

作为一个附带问题,我如何让它在执行过程之前接受/识别代码字以及双引号?截至目前,我只能使用 ./client ... pathname/"name with spaces" ;如果我使用 ./client ... "pathname/name with spaces" 它会显示 stat: no such file or directory 错误。 例如:

./client localhost 4000 "GET 路径名/文件名"

【问题讨论】:

你有什么证据证明:1)read() 将接收客户端发送给它的所有内容(来自套接字的read() 不保证它会读取所有另一方发送,它可能只返回第一次调用read() 时的第一个字节,并且必须再次调用read() 客户端发送的其余内容),以及2)该字符串传递给stat() '\0' 是否终止,就像所有 C 风格的字符串都必须终止一样? 在您了解所有规则之前,没有简单的 TCP 套接字连接。规则 1:永远不要忽略返回码。它们都很重要,其中一些根据价值的不同意味着不同的东西。例如,如果read 返回一个负数,那就是一个错误。如果有兴趣,可以使用perror 查找。返回 0 表示礼貌断开连接。正数是您在提供的缓冲区中可以找到的字节数。 【参考方案1】:

你的问题在这里:

else if(s.st_mode & S_IFREG)

    int fd = open(path, O_RDONLY);
    if(fd < 0)  perror("open"); exit(EXIT_FAILURE); 
    read(fd, buffer, strlen(buffer)); << Change strlen(buffer)
    strcat(buffer, "\n");
    if(write(connSock, buffer, strlen(buffer)) < 0)
     perror("write"); exit(EXIT_FAILURE); 
    close(fd);

strlen(buffer) 可以是任何值,因为您将缓冲区初始化为 1024 字节。内存区域可能被填满了零。 strlen(buffer) 将返回 0,因为第一个字符是空字节。没有任何内容被写入缓冲区,因为read 最终会写入零字节。

【讨论】:

这只是所示代码中的许多错误之一,由于其他错误,它可能甚至没有达到这一点。 确实如此。代码中有很多错误。这是我能找到的第一个。 感谢您的鉴赏。我还是新手。

以上是关于C++ UNIX 帮助 - 简单的 TCP 服务器套接字连接的主要内容,如果未能解决你的问题,请参考以下文章

TCP 环回连接与 Unix 域套接字性能

将 Unix 套接字移植到 Windows [关闭]

TCP 套接字 - 服务器不接受任何连接 UNIX

C++ 使用 send_to 提升 unix 域套接字

Redis-Redis 绑定套接字用unix socket还是tcp socket比较好

雷达 tcp ip socket c++