首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >C++网络,recv()无缘无故失败(?)

C++网络,recv()无缘无故失败(?)
EN

Stack Overflow用户
提问于 2018-08-26 20:43:22
回答 1查看 853关注 0票数 0

我正在用c++编写一个聊天服务器,作为我自己的消遣,但总的来说,我对网络相当陌生。我的知识来自Beej的指南,this site,以及Kurose&Ross的自上而下方法。

我的问题是,我写了类似于你可以在链接中找到的代码,但它不起作用。当我尝试在服务器上使用recv()函数时,程序失败。

我知道recv()可以返回任意数量的字节,但它只返回-1。我知道我需要一个循环来拼凑正在发送的消息,但目前还没有这样的东西。然而,客户端中的send()表示它发送了缓冲区中指定的数量(是的,我知道这可能是大材小用了,但不确定这是不是一个错误)。

对我来说,服务器看起来是...以某种方式封闭了?我很确定我在什么地方搞砸了,有一行代码我真的不太确定(查看评论)。我昨天设法让它工作了,但之后出了点问题。

我对套接字编程和任何类型的网络都是新手,但是函数调用和诸如此类的东西来自指南,我有预感问题会出现在我指定端口和地址的部分,也许字节没有到达服务器,因为我正在将它们发送到其他地方?但是如果accept()起作用了,那不是意味着TCP连接已经形成了吗?之后我就不能使用它了吗?

我使用的是最新版本的Lubuntu linux,如果有帮助的话。

如果你发现了这个问题,你能告诉我如何正确地做吗?无论如何,下面是服务器的代码:

代码语言:javascript
运行
复制
void start() {

    char message[1024] = "";

    int socketfd = socket( AF_INET, SOCK_STREAM, 0 ), opt = 1, new_socket;

    struct sockaddr_in address;
    struct sockaddr_storage cl_addr;
    socklen_t len = sizeof(address);

    if( socketfd != 0 ) {

        address.sin_family = AF_INET;
        address.sin_port = htons( PORT );
        address.sin_addr.s_addr = INADDR_ANY;

        if( setsockopt(socketfd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(int)) < 0 ) {
            perror("Setsockopt failed");
            exit(EXIT_FAILURE);
        }

        if( bind( socketfd, (struct sockaddr*)&address, len ) < 0 ) {           
            perror("Couldn't bind to port");
            exit(EXIT_FAILURE);
        } 

        if( listen( socketfd, 3 ) < 0 ) {
            perror("Listening on port failed");
            exit(EXIT_FAILURE);
        }

        if( (new_socket = accept( socketfd, (struct sockaddr *)&cl_addr, (socklen_t*)&len  ) < 0) ) {
            perror("Couldn't accept request");
            exit(EXIT_FAILURE);
        }

        /// This is where it fails
        std::cout << recv( new_socket, message, 1024, 0) <<  std::endl;
        close(new_socket);
    }
    else {
        perror("Couldn't open socket");
        exit(EXIT_FAILURE);
    }
    close( socketfd );
}

现在是客户端:

代码语言:javascript
运行
复制
int main(void) {

int sockfd;

struct sockaddr_in serv_addr;
char hello[1024] = "Hello";

serv_addr.sin_family = AF_INET; 
serv_addr.sin_port = htons(PORT);

/// I'm not sure about this !! 
inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr);

sockfd = socket(AF_INET, SOCK_STREAM, 0);

if( sockfd == 0 ) {
    perror("Opening socket failed");
    exit(EXIT_FAILURE);
}

if( connect(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) != -1 ) {
    /// Says it sent 1024, but sever doesn't recieve it, what gives ?
    int test = send( sockfd, hello, sizeof(hello), 0);
    std::cout << test << std::endl;
}
else {
    perror("Error");
    exit(EXIT_FAILURE);
}

如您所见,它与链接中的代码相似。服务器代码只是一个函数,代码中还有其他部分,比如创建用户文件,但它们都没有在网络部分使用,所以我不想无缘无故地发布另外800行代码。服务器的main()只是创建一个服务器类的对象并在其上调用start()。

我想在我能改进的地方改进,所以如果你注意到我可以做得更好的地方,请告诉我,是通用的编码风格还是其他什么。此外,这是我在这里的第一个问题,我的第一种语言不是英语,请不要对我太苛刻:)

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-08-26 21:24:59

这是一个括号问题。

这一行:

代码语言:javascript
运行
复制
if( (new_socket = accept( socketfd, (struct sockaddr *)&cl_addr, (socklen_t*)&len  ) < 0) ) {

=运算符相比,<运算符具有更高的评估优先级。

new_socket被赋值为accept() < 0,这是一个错误的表达式,因此new_socket被赋值为零。

这可能就是你想说的:

代码语言:javascript
运行
复制
if (new_socket = accept( socketfd, (struct sockaddr *)&cl_addr, (socklen_t*)&len ) < 0)

但这就不容易出错了:

代码语言:javascript
运行
复制
new_socket = accept( socketfd, (struct sockaddr *)&cl_addr, (socklen_t*)&len  ); 
if (new_socket < 0) {
        perror("Couldn't accept request");
        exit(EXIT_FAILURE);
}
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52026363

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档