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];
精彩评论