c++winsock多线程http服务器

c++ winsock multithread http server

本文关键字:服务器 http 多线程 c++winsock      更新时间:2023-10-16

我是C++的新手,遇到了一个问题,当我连接到服务器(使用浏览器)时,它会发送一个响应,并且在浏览器上显示得很好,但查看它发送网页两次的控制台,页面视图计数器会确认这一点,通过测试,我不确定它的运行顺序。

循环侦听新连接:

    while (true){
    //create temp scoket for cconnetcion
    SOCKET ClientSocket;
    ClientSocket = INVALID_SOCKET;
    // Accept the socket from the client when it tries to connect
    ClientSocket = accept(ListenSocket, NULL, NULL);
    printf("NEWCON" );
    if (ClientSocket == INVALID_SOCKET) {
        printf("accept failed: %dn", WSAGetLastError());
        std::string blah;
        std::cin >> blah;
        closesocket(ListenSocket);
        WSACleanup();
        return 104;
    }
    views += 1;
    AfxBeginThread(RequestProsorses, (LPVOID)ClientSocket);
}

RequestProsorses函数:

UINT  RequestProsorses(LPVOID pParam){
printf("n NEWREC");
SOCKET ClientSocket = (SOCKET)pParam;

 #define DEFAULT_BUFLEN 512
char recvbuf[DEFAULT_BUFLEN];
int conResult, iSendResult;
int recvbuflen = DEFAULT_BUFLEN;
std::string returnVal = "HTTP/1.x 200 OK n Transfer-Encoding: chunked nn <html><body><b>Total Page Views:</b>";
conResult = recv(ClientSocket, recvbuf, recvbuflen, 0);
if (conResult > 0) {
    printf("Bytes received: %dn", conResult);
    //create response to user
    returnVal +=   std::to_string(views) + "</body></html>";
    //printf(returnVal.c_str());
    // Send Responce to user
    iSendResult = send(ClientSocket, returnVal.c_str(), returnVal.length(), 0);
    if (iSendResult == SOCKET_ERROR) {
        //printf("send failed: %dn", WSAGetLastError());
        std::string blah;
        std::cin >> blah;
        closesocket(ClientSocket);
        WSACleanup();
    }
    printf("Bytes sent: %dn", iSendResult);
}
else if (conResult == 0){
    printf("Connection closing...n");
}
else {
    printf("recv failed: %dn", WSAGetLastError());
    std::string blah;
    std::cin >> blah;
    closesocket(ClientSocket);
    WSACleanup();
}
// shutdown the send half of the connection since no more data will be sent
conResult = shutdown(ClientSocket, SD_SEND);
if (conResult == SOCKET_ERROR) {
    printf("shutdown failed: %dn", WSAGetLastError());
    closesocket(ClientSocket);
    WSACleanup();
}
closesocket(ClientSocket);
return 0;
}

控制台输出(仅从一个视图):

NEWCONNEWCON
NEWREC
收到的NEWRECBytes:373
发送的字节数:99
接收的字节数:287
发送的字节数:99

希望这对你来说是足够的信息,如果不是,我当然很乐意发布更多。

if语句检查头端

    for (int i = 0; i <= recvbuflen; i++){
    if (recvbuf[i] == 'n' && (int)recvbuf[i + 1] == -52){
        finished = true;
    }
}

我找到了答案:),感谢@JoachimPileborg和@MartinJames的帮助!简单地说,浏览器发送了第二个请求,由于程序不检查正在查看的页面(无论此时发生什么,它都只是发送相同的页面),在我看来,它只为一个页面请求做了两次相同的事情。浏览器也在尝试评估/favicon.ico。

我已经对代码进行了更改,虽然还没有完成,但它仍然有效,所以如果有人对我所做的更改感兴趣,这里是代码(以防我在没有意识到的情况下修复了其他错误)。

// HTMLtest.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <stdio.h>
#include <string>
#include <iostream>
#include <thread>
#include <afxwin.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#pragma comment(lib, "Ws2_32.lib")

int views = 0;
UINT  RequestProsorses(LPVOID pParam){
    printf("n NEWREC");
    SOCKET ClientSocket = (SOCKET)pParam;
#define DEFAULT_BUFLEN 512
char recvbuf[DEFAULT_BUFLEN];
int conResult, iSendResult;
int recvbuflen = DEFAULT_BUFLEN;
std::string returnVal = "HTTP/1.x 200 OK n Transfer-Encoding: chunked nn <html><body><b>Total Page Views:</b>";
bool finished = false;
do {
    std::cout << "b";
conResult = recv(ClientSocket, recvbuf, recvbuflen, 0);
for (int i = 0; i <= recvbuflen; i++){
    if (recvbuf[i] == 'n' && (int)recvbuf[i + 1] == -52){
        finished = true;
    }
}
if (conResult > 0) {
}
else if (conResult == 0){
    printf("Connection closing...n");
}
else {
    printf("recv failed: %dn", WSAGetLastError());
    std::string blah;
    std::cin >> blah;
    closesocket(ClientSocket);
}

} while (conResult > 0 && finished == false);
printf("Bytes received: %dn", conResult);
std::cout << "RECIVED: " << recvbuf;
//create response to user
returnVal += std::to_string(views) + "</body></html>";
//printf(returnVal.c_str());
// Send Responce to user
iSendResult = send(ClientSocket, returnVal.c_str(), returnVal.length(), 0);
if (iSendResult == SOCKET_ERROR) {
    printf("send failed: %dn", WSAGetLastError());
    std::string blah;
    std::cin >> blah;
    closesocket(ClientSocket);
}
printf("Bytes sent: %dn", iSendResult);

closesocket(ClientSocket);
return 0;
}
int _tmain(int argc, _TCHAR* argv[])
{
WSADATA wsaData;
// Initialize Winsock
int IPresult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (IPresult != 0) {
    printf("WSAStartup failed: %dn", IPresult);
    return 1;
}
struct addrinfo *result = NULL, *ptr = NULL, params;
ZeroMemory(&params, sizeof(params));
params.ai_family = AF_INET;
params.ai_socktype = SOCK_STREAM;
params.ai_protocol = IPPROTO_TCP;
params.ai_flags = AI_PASSIVE;
//resolve the IP address and port to used by the server
IPresult = getaddrinfo(NULL, "80", &params, &result);
if (IPresult != 0) {
    printf("getaddrinfo failed: %dn", IPresult);
    std::string blah;
    std::cin >> blah;
    WSACleanup();
    return 100;
}

SOCKET ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
if (ListenSocket == INVALID_SOCKET) {
    printf("Error at socket(): %ldn", WSAGetLastError());
    std::string blah;
    std::cin >> blah;
    freeaddrinfo(result);
    WSACleanup();
    return 101;
}
// Setup the socket for HTTP
IPresult = bind(ListenSocket, result->ai_addr, (int)result->ai_addrlen);
if (IPresult == SOCKET_ERROR) {
    printf("bind failed with error: %dn", WSAGetLastError());
    std::string blah;
    std::cin >> blah;
    freeaddrinfo(result);
    closesocket(ListenSocket);
    WSACleanup();
    return 102;
}
//Free the memory allocated by "getadderinfo" as its no longe needed
freeaddrinfo(result);
if (listen(ListenSocket, SOMAXCONN) == SOCKET_ERROR) {
    printf("Listen failed with error: %ldn", WSAGetLastError());
    std::string blah;
    std::cin >> blah;
    closesocket(ListenSocket);
    WSACleanup();
    return 103;
}

while (true){
    //create temp scoket for cconnetcion
    SOCKET ClientSocket;
    ClientSocket = INVALID_SOCKET;
    // Accept the socket from the client when it tries to connect
    ClientSocket = accept(ListenSocket, NULL, NULL);
    printf("NEWCON" );
    if (ClientSocket == INVALID_SOCKET) {
        printf("accept failed: %dn", WSAGetLastError());
        std::string blah;
        std::cin >> blah;
        closesocket(ListenSocket);
        WSACleanup();
        return 104;
    }
    views += 1;
    AfxBeginThread(RequestProsorses, (LPVOID)ClientSocket);
}
// cleanup
//closesocket(ClientSocket);
WSACleanup();
return 0;
}

很抱歉它太不整洁了:/