为了账号安全,请及时绑定邮箱和手机立即绑定

C套接字间歇性地重置连接并且没有收到来自python请求的完整请求

C套接字间歇性地重置连接并且没有收到来自python请求的完整请求

红糖糍粑 2022-11-01 16:15:04
我有一个 python 程序,我想通过 http 与 C 程序通信。我在 python 中使用请求将一些 json 数据发送到 C 中的套接字。有时,python 会吐出“由对等方重置连接”错误,我无法弄清楚。当我收到这个错误时,除了请求的内容之外的所有内容都由 C 程序发送和接收。在我的应用程序中,我还从一个用 Go 编写的客户端发出请求。对于那个客户端,我永远不会收到这些错误,这就是为什么我认为我在请求库中缺少一些配置或简单的解决方案。为什么会发生这种情况,什么可以解决我的问题?这是一个简单的例子;套接字的东西显然是我不太熟悉的:C服务器:#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <sys/socket.h>#include <netinet/in.h>#define RECV_BUF_SIZE 1024int main(void){    struct sockaddr_in serv_addr, cli_addr;    serv_addr.sin_family = AF_INET;    serv_addr.sin_addr.s_addr = INADDR_ANY;    serv_addr.sin_port = htons(8080);    int option = 1;    int socketfd = socket(AF_INET, SOCK_STREAM, 0);    setsockopt(socketfd, SOL_SOCKET, SO_REUSEADDR, &option, sizeof(option));    if (socketfd < 0)    {        perror("failed to start socket");        exit(1);    }    if (bind(socketfd, (struct sockaddr*) &serv_addr, sizeof(serv_addr)) < 0)    {        perror("failed to bind");        exit(1);    }    if (listen(socketfd, 1000) != 0)    {        perror("listen error");        exit(1);    }    char buf[RECV_BUF_SIZE];    while (1)    {        int addrlen = sizeof(cli_addr);        int clientfd = accept(socketfd, (struct sockaddr*) &cli_addr, &addrlen);        if (clientfd < 0)        {            perror("accept error");        }        else        {            int n_recv = recv(clientfd, buf, RECV_BUF_SIZE, 0);            // print everything, character by character.            char* tmp_buf = buf;            while (n_recv--) printf("%c", *tmp_buf++);            printf("\n\n****************************\n\n");            FILE* res = fdopen(clientfd, "w");            fprintf(res, "HTTP/1.1 200 OK\r\n\r\n");            fclose(res);            shutdown(clientfd, SHUT_RDWR);            close(clientfd);        }    }}Python 请求脚本:import requestsjson_data = {    "hello": "thanks"}requests.post("http://localhost:8080", json=json_data)谢谢!
查看完整描述

1 回答

?
喵喵时光机

TA贡献1846条经验 获得超7个赞

关于服务器与客户端的通信,有几个小问题,比如不正确的变量类型和缺乏错误检查。


我在我的评论前面加上了>>'条件编译'来展示我如何用建议的改进替换了 OPs 代码的某些部分。


警告:由于服务器不知道从客户端接收的预期字节数,因此答案不包括循环,试图检索客户端预期的所有字节


char buf[ RECV_BUF_SIZE +1 ];  // >> +1 for string terminator


while (1)

{

    // >> the third parameter is a 'socklen_t', not an 'int'

    socklen_t addrlen = sizeof(cli_addr);

    int clientfd = 

        accept(socketfd, (struct sockaddr*) &cli_addr, &addrlen);

    if (clientfd < 0)

    {

        perror("accept error");

    }


    else

    {

        // >>recv() returns a `ssize_t`, not an `int`

        ssize_t n_recv = recv(clientfd, buf, RECV_BUF_SIZE, 0);


        #if 0


            // >>this takes WAY too long, so the connection

            // >>could timeout

            // print everything, character by character.

            char* tmp_buf = buf;

            while (n_recv--) printf("%c", *tmp_buf++);


        #else


            if( n_recv < 0 )

            {  // then an error occurred

                perror( "recv failed" );

                write( clientfd, 

                       "receive error", 

                       sizeof( "receive error" ) );

                close( clientfd );

            }


            else if( n_recv == 0 )

            {  // then client closed connection

                printf( "%s\n", 

                        "client closed connection" );

                close( clientfd );

            }


            else

            { // some data received from client

                buf[ n_recv ] = '\0';  // terminate string

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

            }


        #endif


        printf("\n\n****************************\n\n");


        #if 0


            FILE* res = fdopen(clientfd, "w");

            fprintf(res, "HTTP/1.1 200 OK\r\n\r\n");

            fclose(res);

            shutdown(clientfd, SHUT_RDWR);

            close(clientfd);


        #else


            ssize_t writeBytes;

            if( (writeBytes = 

                 write( clientfd, 

                        "HTTP/1.1 200 OK\r\n\r\n", 

                        strlen( "HTTP/1.1 200 OK\r\n\r\n" ) ) ) 

                        != strlen( "HTTP/1.1 200 OK\r\n\r\n" ) )

            { // then incomplete write

                printf( "%s\n",  

                        "write didn't write all bytes to client" );

            }


            close( clientfd );


        #endif

    }

}

分享

编辑

跟随关于服务器与客户端的通信,有几个小问题,比如不正确的变量类型和缺乏错误检查。


我在我的评论前面加上了>>'条件编译'来展示我如何用建议的改进替换了 OPs 代码的某些部分。


警告:由于服务器不知道从客户端接收的预期字节数,因此答案不包括循环,试图检索客户端预期的所有字节


char buf[ RECV_BUF_SIZE +1 ];  // >> +1 for string terminator


while (1)

{

    // >> the third parameter is a 'socklen_t', not an 'int'

    socklen_t addrlen = sizeof(cli_addr);

    int clientfd = 

        accept(socketfd, (struct sockaddr*) &cli_addr, &addrlen);

    if (clientfd < 0)

    {

        perror("accept error");

    }


    else

    {

        // >>recv() returns a `ssize_t`, not an `int`

        ssize_t n_recv = recv(clientfd, buf, RECV_BUF_SIZE, 0);


        #if 0


            // >>this takes WAY too long, so the connection

            // >>could timeout

            // print everything, character by character.

            char* tmp_buf = buf;

            while (n_recv--) printf("%c", *tmp_buf++);


        #else


            if( n_recv < 0 )

            {  // then an error occurred

                perror( "recv failed" );

                write( clientfd, 

                       "receive error", 

                       sizeof( "receive error" ) );

                close( clientfd );

            }


            else if( n_recv == 0 )

            {  // then client closed connection

                printf( "%s\n", 

                        "client closed connection" );

                close( clientfd );

            }


            else

            { // some data received from client

                buf[ n_recv ] = '\0';  // terminate string

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

            }


        #endif


        printf("\n\n****************************\n\n");


        #if 0


            FILE* res = fdopen(clientfd, "w");

            fprintf(res, "HTTP/1.1 200 OK\r\n\r\n");

            fclose(res);

            shutdown(clientfd, SHUT_RDWR);

            close(clientfd);


        #else


            ssize_t writeBytes;

            if( (writeBytes = 

                 write( clientfd, 

                        "HTTP/1.1 200 OK\r\n\r\n", 

                        strlen( "HTTP/1.1 200 OK\r\n\r\n" ) ) ) 

                        != strlen( "HTTP/1.1 200 OK\r\n\r\n" ) )

            { // then incomplete write

                printf( "%s\n",  

                        "write didn't write all bytes to client" );

            }


            close( clientfd );


        #endif

    }

}



查看完整回答
反对 回复 2022-11-01
  • 1 回答
  • 0 关注
  • 89 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号