2014-09-19 2 views
0

오히려 C++에 익숙하지 않고 문제가 생겼습니다. 브라우저를 사용하여 서버에 연결하면 응답이 잘 보내고 브라우저에서 문제없이 보입니다. 그것이 웹 페이지를 두 번 보낸 콘솔, 페이지 뷰 카운터가 이것을 확인합니다. 테스트에서 실행 순서가 확실하지 않습니다. 새로운 연결을 듣기C++ winsock multithread http server

루프 :

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: %d\n", 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 \n\n <html><body><b>Total Page Views:</b>"; 

conResult = recv(ClientSocket, recvbuf, recvbuflen, 0); 
if (conResult > 0) { 
    printf("Bytes received: %d\n", 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: %d\n", WSAGetLastError()); 
     std::string blah; 
     std::cin >> blah; 
     closesocket(ClientSocket); 
     WSACleanup(); 
    } 
    printf("Bytes sent: %d\n", iSendResult); 
} 
else if (conResult == 0){ 
    printf("Connection closing...\n"); 
} 
else { 
    printf("recv failed: %d\n", 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: %d\n", WSAGetLastError()); 
    closesocket(ClientSocket); 
    WSACleanup(); 
} 

closesocket(ClientSocket); 

return 0; 
} 

콘솔 출력 (형태 하나만 뷰)

NEWCONNEWCON
NEWREC
NEWRECBytes recived : 373
바이트 전송 : 99
바이트가 recevied : 287
바이트 전송 : 나는 물론 더 게시 할 행복하지 않으면, 당신을 위해 충분한 정보의 99

희망을.

문이 헤더

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

당신은 * 전체 * 요청을받은 때까지 아무 것도 보내지한다. –

+1

또한 스레드에서 오류가 발생하면 'WSACleanup'을 호출합니다. 물론 메인 스레드를 포함하여 전체 * 프로세스 *를 정리합니다. 그러면 다른 소켓이 아직 열려있는 상태에서 정의되지 않은 동작이 발생할 가능성이 높습니다. –

+1

그리고 마지막으로 쓰레드에서 마지막으로'closesocket'을 수행하기 때문에'shutdown'을 할 필요가 없습니다. 당신이 더 많은 것을 읽을 것이지만 더 보내지 않기를 기대한다면, 송신 측의'shutdown' 만하십시오. –

답변

0

의 적 끝을 확인하는 경우에 나는 거기에 도움을 @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 \n\n <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: %d\n", WSAGetLastError()); 
    std::string blah; 
    std::cin >> blah; 
    closesocket(ClientSocket); 
} 



} while (conResult > 0 && finished == false); 

printf("Bytes received: %d\n", 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: %d\n", WSAGetLastError()); 
    std::string blah; 
    std::cin >> blah; 
    closesocket(ClientSocket); 
} 
printf("Bytes sent: %d\n", 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: %d\n", 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: %d\n", 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(): %ld\n", 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: %d\n", 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: %ld\n", 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: %d\n", WSAGetLastError()); 
     std::string blah; 
     std::cin >> blah; 
     closesocket(ListenSocket); 
     WSACleanup(); 
     return 104; 
    } 

    views += 1; 

    AfxBeginThread(RequestProsorses, (LPVOID)ClientSocket); 

} 

// cleanup 
//closesocket(ClientSocket); 
WSACleanup(); 
return 0; 
} 

죄송합니다 그것이 얼마나 어수선한 :/

+0

'Transfer-Encoding : chunked' 응답 헤더를 제거해야합니다. [RFC 2616 섹션 3.6.1] (http://tools.ietf.org/html/rfc2616#section-3.6.1)을 준수하는 청크 형식으로 응답 데이터를 보내지 않으므로 브라우저에 너는. –