开发者

C Prog - Keeping a web server constantly listening

I am trying to learn winsock programming using online tutorials. This example is from the MSDN library, although modified. I have compiled it and it seems to be working fine for only one request. After handling a single request the server exits. I have read handling multiple request and making the server persistent can be done through threads, but have no idea how do so and no helpful examples found over the internet. Please help.

#undef UNICODE

#define WIN32_LEAN_AND_MEAN

#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdlib.h>
#include <stdio.h>

// Need to link with Ws2_32.lib
#pragma comment (lib, "Ws2_32.lib")
// #pragma comment (lib, "Mswsock.lib")

#define DEFAULT_BUFLEN 4096
#define DEFAULT_PORT "27015"
char recvbuf[DEFAULT_BUFLEN];

void handleBuffer()
{
recvbuf[DEFAULT_BUFLEN-1]='\0';
printf("\n************The server has received the following request***************\n");
printf("%s",recvbuf);
}

int __cdecl main(void)
{
WSADATA wsaData;
SOCKET ListenSocket = INVALID_SOCKET,
       ClientSocket = INVALID_SOCKET;
struct addrinfo *result = NULL,hints;
char* sendbuf = "HTTP/1.0 200 OK\r\nServer: Test\r\nContent-Type: text/HTML\r\n\r\n<html><title>Test Server</title><body><s开发者_高级运维pan style=\"color:#2032DC; font-family:arial; font-size:large; position:absolute; left:4%;\">This is test server responding.</span></body></html>";
int iResult, iSendResult;
int recvbuflen = DEFAULT_BUFLEN;
char e;

// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if (iResult != 0) {
    printf("WSAStartup failed with error: %d\n", iResult);
    return 1;
}
else
    printf("\nInitialising winsock...done");

ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
hints.ai_flags = AI_PASSIVE;
printf("\n");

// Resolve the server address and port
iResult = getaddrinfo(NULL, DEFAULT_PORT, &hints, &result);
if ( iResult != 0 ) {
    printf("getaddrinfo failed with error: %d\n", iResult);
    WSACleanup();
    return 1;
}
else
    printf("\nResolving server address...done");
//localhost:27015/
// Create a SOCKET for connecting to server

ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
if (ListenSocket == INVALID_SOCKET) {
    printf("socket failed with error: %ld\n", WSAGetLastError());
    freeaddrinfo(result);
    WSACleanup();
    return 1;
}
else
    printf("\nCreating connection socket...done");

// Setup the TCP listening socket
iResult = bind( ListenSocket, result->ai_addr, (int)result->ai_addrlen);
if (iResult == SOCKET_ERROR) {
    printf("bind failed with error: %d\n", WSAGetLastError());
    freeaddrinfo(result);
    closesocket(ListenSocket);
    WSACleanup();
    return 1;
}
else
    printf("\nCreating listening socket...done");
    printf("\nWaiting for connection... ");

freeaddrinfo(result);

iResult = listen(ListenSocket, SOMAXCONN);

if (iResult == SOCKET_ERROR) {
    printf("listen failed with error: %d\n", WSAGetLastError());
    closesocket(ListenSocket);
    WSACleanup();
    return 1;
}

    // Accept a client socket
    ClientSocket = accept(ListenSocket, NULL, NULL);
    if (ClientSocket == INVALID_SOCKET) {
        printf("accept failed with error: %d\n", WSAGetLastError());
        closesocket(ListenSocket);
        WSACleanup();
        return 1;
    }

    // No longer need server socket
    closesocket(ListenSocket);

    iResult = recv(ClientSocket, recvbuf, recvbuflen,0);
    if (iResult > 0)
    {
        printf("Bytes received: %d\n", iResult);
    }
    else if (iResult == 0)
        printf("Connection closing...\n");
    else
    {
        printf("recv failed with error: %d\n", WSAGetLastError());
        closesocket(ClientSocket);
        WSACleanup();
        return 1;
    }


    iSendResult = send(ClientSocket,sendbuf,(int)strlen(sendbuf), 0 );
        if (iSendResult == SOCKET_ERROR)
        {
            printf("send failed with error: %d\n", WSAGetLastError());
            closesocket(ClientSocket);
            WSACleanup();
            return 1;
        }
    printf("Bytes sent: %d\n", iSendResult);
    handleBuffer();

    // shutdown the connection since we're done
    iResult = shutdown(ClientSocket, SD_SEND);
    if (iResult == SOCKET_ERROR) {
        printf("shutdown failed with error: %d\n", WSAGetLastError());
        closesocket(ClientSocket);
        WSACleanup();
        return 1;
    }
// cleanup
closesocket(ClientSocket);
WSACleanup();
printf("\n\nPress any key to quit.");

getch();
return 0;
}


It's straight forward.

  ClientSocket = accept(ListenSocket, NULL, NULL);

This returns the socket used to communicate with the connected client, all you have to do is do a read/write loop for this socket and stick it into a new Thread. Meanwhile, keep your main looping on the accept().

What's you don't get?

EDIT

Assuming you're going to use Posix Threads, have a look at this http://www.yolinux.com/TUTORIALS/LinuxTutorialPosixThreads.html

After mastering this, you might need more power and flexibility: check this out http://www.lowtek.com/sockets/select.html

You can use select to avoid using threads, you can use it to distribute your clients through threads (like 1..N client is/are managed by 1 thread)

Remark

Wait there's a hole in your code:

int recvbuflen = DEFAULT_BUFLEN;

then you use this into the receive.. it's bad, this might produce an overflow, in order to solve this, declare your buffer as: char recvbuf[DEFAULT_BUFLEN + 1];

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜