C服务器 - "连接被重置" [英] C Server - "The connection was reset"

查看:202
本文介绍了C服务器 - "连接被重置"的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我修改beej指南联网为例(如下图所示),传回一个HTML响应到浏览器。我得到连接被重置每隔几刷新,似乎并不能找出原因?其,就好像它是在关闭连接它发出的HTML响应之前

任何意见或建议,调试?

编辑:它有时正确的数据传递到浏览器

下面是code:

  / *
 ** server.c - 流套接字服务器演示
 * /#包括LT&;&iostream的GT;
#包括LT&;串GT;
#包括LT&;&stdio.h中GT;
#包括LT&;&stdlib.h中GT;
#包括LT&;&unistd.h中GT;
#包括LT&;&errno.h中GT;
#包括LT&;&string.h中GT;
#包括LT&; SYS / types.h中>
#包括LT&; SYS / socket.h中>
#包括LT&; netinet / in.h中>
#包括LT&;&netdb.h中GT;
#包括LT&; ARPA / inet.h>
#包括LT&; SYS / wait.h>
#包括LT&;&signal.h中GT;#定义端口8080//该端口的用户将被连接到#定义积压10000 //多少挂起的连接队列将举行使用命名空间std;无效sigchld_handler(int类型)
{
    而(waitpid函数(-1,NULL,WNOHANG)大于0);
}//获取套接字地址,IPv4或IPv6:
无效* get_in_addr(结构sockaddr * SA)
{
    如果(SA->上sa_family == AF_INET){
        返回及(((结构SOCKADDR_IN *)SA) - GT; sin_addr);
    }    返回及(((结构* sockaddr_in6的)SA) - GT; sin6_addr);
}INT主要(无效)
{
    INT的sockfd,new_fd; //监听sock_fd,在new_fd新的连接
    结构addrinfo中的提示,* servinfo,* P;
    结构sockaddr_storage their_addr; //连接器的地址信息
    socklen_t的sin_size;
    结构sigaction的SA;
    INT是= 1;
    个char [INET6_ADDRSTRLEN]
    INT RV;    memset的(安培;提示,0,sizeof的提示);
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_flags = AI_PASSIVE; //用我的IP    如果((RV =的getaddrinfo(NULL,PORT&放大器;提示,&放大器;!servinfo))= 0){
        fprintf中(标准错误的getaddrinfo:%S \\ n,gai_strerror(RV));
        返回1;
    }    //遍历所有的结果,并结合第一个我们可以
    为(P = servinfo; P!= NULL; P = P-> ai_next){
        如果((的sockfd =插座(对GT; ai_family,P-> ai_socktype,
                        P-> ai_protocol))== -1){
            PERROR(服务器:套接字);
            继续;
        }        如果(setsockopt的(的sockfd,SOL_SOCKET,SO_REUSEADDR,&安培;是的,
                    的sizeof(INT))== -1){
            PERROR(setsockopt的);
            出口(1);
        }        如果(绑定(的sockfd,P-> ai_addr,P-> ai_addrlen)== -1){
            接近(的sockfd);
            PERROR(服务器:绑定);
            继续;
        }        打破;
    }    如果(P == NULL){
        fprintf中(标准错误,服务器:无法绑定\\ n);
        返回2;
    }    freeaddrinfo(servinfo); //所有这种结构完成    如果(听(的sockfd,积压)== -1){
        PERROR(听);
        出口(1);
    }    sa.sa_handler = sigchld_handler; //获得全部死亡过程
    sigemptyset(安培; sa.sa_mask);
    sa.sa_flags = SA_RESTART;
    如果(的sigaction(SIGCHLD,&安培; SA,NULL)== -1){
        PERROR(sigaction的);
        出口(1);
    }    的printf(服务器:等待连接... \\ n);    而(1){//主接受()循环
        sin_size = sizeof的their_addr;
        new_fd =接受(的sockfd,(结构sockaddr *)及their_addr,&安培; sin_size);
        如果(new_fd == -1){
            COUT<< 接受失败<< ENDL;
            继续;
        }        inet_ntop(their_addr.ss_family,
                get_in_addr((结构sockaddr *)及their_addr)
                S,sizeof的S);
        的printf(服务器:得到来自%s \\ n连接,S);        如果(!叉()){//这是子进程
            接近(的sockfd); //子不需要监听
            串响应=HTTP / 1.0 200 OK\\r\
\\r\
<html><head><title>Test</title></head><body>ok!</body></html>\";
            如果(发送(new_fd,response.c_str(),response.length(),0)== -1)
                COUT&LT;&LT; 错误&LT;&LT; ENDL;
            关闭(new_fd);
            COUT&LT;&LT; 发送。 &LT;&LT; ENDL;
            出口(0);
        }
        关闭(new_fd); //父不需要这个
    }    返回0;
}


解决方案

因此​​,这里有2个错误(3真的,最后一个是,如果你想谈论到浏览器,你真的要正确实现HTTP这是非平凡)


  1. 你当你接受一个客户端会立即发送响应。浏览器作为一个有点慢则可能会收到响应甚至在它完成发送请求 - which'll搞乱浏览器


  2. 你不读请求。这意味着,当你关闭套接字,还会有未读的数据,这将导致一个TCP RST(这将导致连接复位......错误)当您关闭套接字发送。在某些情况下,浏览器将读出的响应这种情况发生之前,在其他情况下,可能没有,(在某些情况下,我想你有没有内容长度,它会混淆:头,所以浏览器没有按知道这是否应该WS当它遇到一个TCP RST)接收更多的数据。这种特殊的情况进行了说明更好这里


I modified beej's guide to networking example (as seen below) to pass back a html response to a browser. I am getting "The connection was reset" every few refreshes, and can't seem to figure out why? Its as if it is closing the connection before it sends out the html response.

Any ideas, or suggestions to debug?

Edit: It does sometimes pass the correct data to the browser.

Here is the code:

/*
 ** server.c -- a stream socket server demo
 */

#include <iostream>
#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <signal.h>

#define PORT "8080"  // the port users will be connecting to

#define BACKLOG 10000    // how many pending connections queue will hold

using namespace std;

void sigchld_handler(int s)
{
    while(waitpid(-1, NULL, WNOHANG) > 0);
}

// get sockaddr, IPv4 or IPv6:
void *get_in_addr(struct sockaddr *sa)
{
    if (sa->sa_family == AF_INET) {
        return &(((struct sockaddr_in*)sa)->sin_addr);
    }

    return &(((struct sockaddr_in6*)sa)->sin6_addr);
}

int main(void)
{
    int sockfd, new_fd;  // listen on sock_fd, new connection on new_fd
    struct addrinfo hints, *servinfo, *p;
    struct sockaddr_storage their_addr; // connector's address information
    socklen_t sin_size;
    struct sigaction sa;
    int yes=1;
    char s[INET6_ADDRSTRLEN];
    int rv;

    memset(&hints, 0, sizeof hints);
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_flags = AI_PASSIVE; // use my IP

    if ((rv = getaddrinfo(NULL, PORT, &hints, &servinfo)) != 0) {
        fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
        return 1;
    }

    // loop through all the results and bind to the first we can
    for(p = servinfo; p != NULL; p = p->ai_next) {
        if ((sockfd = socket(p->ai_family, p->ai_socktype,
                        p->ai_protocol)) == -1) {
            perror("server: socket");
            continue;
        }

        if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes,
                    sizeof(int)) == -1) {
            perror("setsockopt");
            exit(1);
        }

        if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
            close(sockfd);
            perror("server: bind");
            continue;
        }

        break;
    }

    if (p == NULL)  {
        fprintf(stderr, "server: failed to bind\n");
        return 2;
    }

    freeaddrinfo(servinfo); // all done with this structure

    if (listen(sockfd, BACKLOG) == -1) {
        perror("listen");
        exit(1);
    }

    sa.sa_handler = sigchld_handler; // reap all dead processes
    sigemptyset(&sa.sa_mask);
    sa.sa_flags = SA_RESTART;
    if (sigaction(SIGCHLD, &sa, NULL) == -1) {
        perror("sigaction");
        exit(1);
    }

    printf("server: waiting for connections...\n");

    while(1) {  // main accept() loop
        sin_size = sizeof their_addr;
        new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size);
        if (new_fd == -1) {
            cout << "accept fail" << endl;
            continue;
        }

        inet_ntop(their_addr.ss_family,
                get_in_addr((struct sockaddr *)&their_addr),
                s, sizeof s);
        printf("server: got connection from %s\n", s);

        if (!fork()) { // this is the child process
            close(sockfd); // child doesn't need the listener
            string response = "HTTP/1.0 200 OK\r\n\r\n<html><head><title>Test</title></head><body>ok!</body></html>";
            if (send(new_fd, response.c_str(), response.length(), 0) == -1)
                cout << "error" << endl;
            close(new_fd);
            cout << "sent." << endl;
            exit(0);
        }
        close(new_fd);  // parent doesn't need this
    }

    return 0;
}

解决方案

So there's 2 errors here (3 really, the last one being that if you want to talk to a browser you really have to implement HTTP properly which is non-trivial)

  1. You're sending the response immediately when you accept a client. A browser being a bit slow might then receive a response even before it's finished sending a request - which'll confuse the browser.

  2. You're not reading the request. That means when you close the socket, there'll be unread data, this'll lead to a TCP RST (which causes "connection reset .... " errors) being sent when you close the socket. In some cases the browser would have read the response before that happens, in other cases it might not, (and in some cases, I'd guess it'll be confused as you have no Content-Length: header, so the browser doesn't know if it ws supposed to receive more data when it encounters a TCP RST). This particular case is described better here

这篇关于C服务器 - &QUOT;连接被重置&QUOT;的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆