You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++手写HTTP Server显示监听但curl连接被拒绝求助

HTTP服务器连接拒绝问题排查与修复

我用C++编写了一个HTTP Server,运行后控制台显示:

*** Listening on ADDRESS: 127.0.0.1 PORT: 80 ***
Waiting for a new connection

但在另一个终端执行curl http://127.0.0.1/时,返回错误:curl: (7) Failed to connect to 127.0.0.1 port 80: Connection refused,需要解决这个连接问题。

我的server.h文件

#include <iostream>
#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <string>

class Server {
    public:
        Server();
        Server(std::string ip_address,int port);
        ~Server();
        
        void startListen();
    private:
        int m_socket;
        int port;
        std::string ip_address;
        long message_in;
        unsigned int m_socket_address_len;
        void acceptConnection(int &new_socket);
        std::string buildResponse();
        void sendResponse();
        int m_new_socket;
        std::string server_message;
        int server_start();
        void close_server();
        struct sockaddr_in m_socketAddress;
};

我的server.cpp文件

#include "server.h"

#include <sstream>
#include <unistd.h>

using namespace std;

const int BUFFER_SIZE = 30720;

Server::Server(std::string ip_address,int port)
{
    this->ip_address = ip_address;
    this->port = port;
    this->m_socket_address_len = sizeof(m_socketAddress);
    this->server_message = buildResponse();
    int x = server_start();    
}

Server::Server()
{
}

Server::~Server()
{
}

int Server::server_start()
{
    m_socket = socket(AF_INET, SOCK_STREAM, 0);
    if(m_socket < 0)
    {
        return 1;
    }
    m_socketAddress.sin_family = AF_INET;
    m_socketAddress.sin_port = htons(port);
    m_socketAddress.sin_addr.s_addr = inet_addr(ip_address.c_str());
    if (bind(m_socket,(sockaddr *)&m_socketAddress, m_socket_address_len) < 0)
    {
        return 1;
    }
    return 0;
}
void Server :: close_server()
{
    close(m_socket);
    exit(0);
}

void Server :: startListen()
{
    if(listen(m_socket,20)<0)
    {
        cout << "Connection Failed" << endl;
    }
    cout  << "\n*** Listening on ADDRESS: " << inet_ntoa(m_socketAddress.sin_addr) << " PORT: " << ntohs(m_socketAddress.sin_port) << " ***\n\n";
    int bytesReceived;

    while (true)
    {
        cout << " Waiting for a new connection " << endl;
        acceptConnection(m_new_socket);

        char buffer[BUFFER_SIZE] = {0};
        bytesReceived = read(m_new_socket, buffer, BUFFER_SIZE);
        if (bytesReceived < 0)
        {
            cout << "Failed to read bytes from client socket connection" << endl;
        }
        cout << " Received Request from client " << endl;
        sendResponse();
        close(m_new_socket);
    }
}

std::string Server :: buildResponse()
{
    std::string htmlFile = "<!DOCTYPE html><html lang=\"en\"><body><h1> HOME </h1><p> Hello from your Server :) </p></body></html>";
    std::ostringstream ss;
    ss << "HTTP/1.1 200 OK\nContent-Type: text/html\nContent-Length: " << htmlFile.size() << "\n\n" << htmlFile;

    return ss.str();
}

void Server :: acceptConnection (int &new_socket)
{
    new_socket = accept(m_socket, (sockaddr *)&m_socketAddress, &m_socket_address_len);
}

void Server :: sendResponse()
{
    long bytesSent;

    bytesSent = write(m_new_socket, server_message.c_str(), server_message.size());
    if (bytesSent == server_message.size())
    {
        cout << "Server responded to client" << endl;
    }
}

int main()
{
    //http_server = Server();
    Server server = Server("127.0.0.1",80);
    //  bind(server.m_socket, server.ip_address, sizeof())
    server.startListen();
    return 0; 
}

问题原因及修复方案

1. 特权端口权限问题

在Unix-like系统中,1-1024端口属于特权端口,普通用户无法绑定。你的程序用普通用户运行时,bind调用会失败,但代码没有处理这个错误,导致程序继续输出监听信息,实际socket并未绑定成功,无法接受连接。

修复:

  • 用root权限运行程序,比如sudo ./your_server;
  • 改用1024以上的端口(如8080),修改main中的端口参数:Server server = Server("127.0.0.1",8080);,测试时用curl http://127.0.0.1:8080/。

2. 缺失错误检查逻辑

server_start中socket或bind失败时返回1,但构造函数未检查这个返回值,导致初始化失败后程序仍继续执行,输出错误的监听状态。

修复:
在构造函数中添加错误检查,初始化失败时直接退出:

Server::Server(std::string ip_address,int port)
{
    this->ip_address = ip_address;
    this->port = port;
    this->m_socket_address_len = sizeof(m_socketAddress);
    this->server_message = buildResponse();
    int x = server_start();    
    if (x != 0) {
        std::cerr << "服务器初始化失败:socket或bind调用出错" << std::endl;
        exit(EXIT_FAILURE);
    }
}

3. accept调用未做有效性检查

accept可能调用失败,但代码未检查返回的新socket是否有效,直接执行read和write会引发错误。

修复:
在acceptConnection后添加有效性检查:

void Server :: startListen()
{
    if(listen(m_socket,20)<0)
    {
        std::cerr << "监听失败" << std::endl;
        exit(EXIT_FAILURE);
    }
    cout  << "\n*** Listening on ADDRESS: " << inet_ntoa(m_socketAddress.sin_addr) << " PORT: " << ntohs(m_socketAddress.sin_port) << " ***\n\n";
    int bytesReceived;

    while (true)
    {
        cout << " Waiting for a new connection " << endl;
        acceptConnection(m_new_socket);
        if (m_new_socket < 0) {
            std::cerr << "接受连接失败" << std::endl;
            continue;
        }

        char buffer[BUFFER_SIZE] = {0};
        bytesReceived = read(m_new_socket, buffer, BUFFER_SIZE);
        if (bytesReceived < 0)
        {
            std::cerr << "读取客户端数据失败" << std::endl;
        }
        cout << " Received Request from client " << endl;
        sendResponse();
        close(m_new_socket);
    }
}

内容的提问来源于stack exchange,提问作者Alphalaser

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 07:24:54