Knowledge Base Nr: 00249 socketserver_berk.cpp - http://www.swe-kaiser.de

Win32: WinCE: Implementierung HTTP Server (Socket Server)

  
//hWnd != NULL gibt im fehlerfall messagebox aus
class CWinCESupport
{
...
static int StartServer(HWND hWnd, int nPortNo, int nTimeOutMs, CString& strRecv);
static int SendAndReceiveSocket(HWND hWnd, LPCTSTR lpwszHost, LPCTSTR lpwszReq, int nPortNo, CString& strError);
};


int CWinCESupport::StartServer(HWND hWnd, int nPortNo, int nTimeOutMs, CString& strError)
{
strError = "";

int index = 0; // Integer index
int iReturn; // Return value of recv function
char szServerA[4000]; // ASCII string
TCHAR szServerW[4000]; // Unicode string
TCHAR szError[4000]; // Error message string

SOCKET WinSocket = INVALID_SOCKET; // Window socket
SOCKET ClientSock = INVALID_SOCKET; // Socket for communicating
// between the server and client
SOCKADDR_IN local_sin; // Local socket address
SOCKADDR_IN accept_sin; // Receives the address of the
// connecting entity
int accept_sin_len; // Length of accept_sin

WSADATA WSAData; // Contains details of the Winsock

// Initialize Winsock.
if (WSAStartup (MAKEWORD(1,1), &WSAData) != 0)
{
wsprintf (szError, TEXT("WSAStartup failed. Error: %d"), WSAGetLastError ());
if (hWnd)
::MessageBox (hWnd, szError, TEXT("Error"), MB_OK);
strError = szError;
return -1;
}

// Create a TCP/IP socket, WinSocket.
if ((WinSocket = socket (AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
{
wsprintf (szError, TEXT("Allocating socket failed. Error: %d"), WSAGetLastError ());
if (hWnd)
::MessageBox (hWnd, szError, TEXT("Error"), MB_OK);
strError = szError;
return -2;
}

// Fill out the local socket's address information.
local_sin.sin_family = AF_INET;
local_sin.sin_port = htons (nPortNo);
local_sin.sin_addr.s_addr = htonl (INADDR_ANY);

// Associate the local address with WinSocket.
if (bind (WinSocket,
(struct sockaddr *) &local_sin,
sizeof (local_sin)) == SOCKET_ERROR)
{
wsprintf (szError, TEXT("Binding socket failed. Error: %d"), WSAGetLastError ());
if (hWnd)
::MessageBox (hWnd, szError, TEXT("Error"), MB_OK);
strError = szError;
closesocket (WinSocket);
return -3;
}

// Establish a socket to listen for incoming connections.
const int MAXCONNECTIONS = 1;
if (listen (WinSocket, MAXCONNECTIONS) == SOCKET_ERROR)
{
wsprintf (szError, TEXT("Listening to the client failed. Error: %d"), WSAGetLastError ());
if (hWnd)
::MessageBox (hWnd, szError, TEXT("Error"), MB_OK);
strError = szError;
closesocket (WinSocket);
return -4;
}

accept_sin_len = sizeof (accept_sin);

// Accept an incoming connection attempt on WinSocket.
ClientSock = accept (WinSocket,
(struct sockaddr *) &accept_sin,
(int *) &accept_sin_len);

// Stop listening for connections from clients.
closesocket (WinSocket);

if (ClientSock == INVALID_SOCKET)
{
wsprintf (szError, TEXT("Accepting connection with client failed."), TEXT(" Error: %d"), WSAGetLastError ());
if (hWnd)
::MessageBox (hWnd, szError, TEXT("Error"), MB_OK);
strError = szError;
return -5;
}

DWORD dwNow = ::GetTickCount();
for (;;)
{
int nTimeEllapsed = ::GetTickCount() - dwNow;
if (nTimeEllapsed > nTimeOutMs)
{
wsprintf (szError, TEXT("Timeout!"));
if (hWnd)
::MessageBox (hWnd, szError, TEXT("Error"), MB_OK);
strError = szError;
break;
}

// Receive data from the client.
iReturn = recv (ClientSock, szServerA, sizeof (szServerA), 0);

// Check if there is any data received. If there is, display it.
if (iReturn == SOCKET_ERROR)
{
wsprintf (szError, TEXT("No data is received, recv failed.")
TEXT(" Error: %d"), WSAGetLastError ());
if (hWnd)
::MessageBox (hWnd, szError, TEXT("Error"), MB_OK);
strError = szError;
break;
}
else if (iReturn == 0)
{
break;
}
else
{
// Convert the ASCII string to the Unicode string.
for (index = 0; index < iReturn; index++)
{
szServerW[index] = szServerA[index];
strError += szServerA[index];
}

//erst komplette anforderung lesen und dann antworten
if (strError.Find(TEXT("\r\n\r\n")) >= 0)
{
// Send a string from the server to the client.
char szAnswer[2000] = "HTTP/1.1 200 OK\n\r"
"Content-type: text/plain\n\r"
"Server: RemoteWebCE 1.0\n\r"
"Pragma: no-cache\n\r"
"Cache-Control: no-cache, must-revalidate\n\r"
"Expires: Thu, 01 Dec 1994 16:00:00 GMT\n\r"
"\n\r"
""
"Das ist mein erster selbstprogrammierter WinCE HTTP Server.\n\r";

if (send (ClientSock, szAnswer, strlen(szAnswer) + 1, 0) == SOCKET_ERROR)
{
wsprintf (szError,
TEXT("Sending data to the client failed. Error: %d"),
WSAGetLastError ());
if (hWnd)
::MessageBox (hWnd, szError, TEXT("Error"), MB_OK);
strError = szError;
}

break;
}
}
}

// Disable both sending and receiving on ClientSock.
shutdown (ClientSock, 0x02);

// Close ClientSock.
closesocket (ClientSock);

WSACleanup ();

return 0;
}

///////////////////////////////////
// sample usage

#include "../../msvc60/cpp_classes/WinCESupport.h"

BOOL CWincehttpDlg::OnInitDialog()
{
...
int nErr = SetTimer(1, 200, NULL); //ACHTUNG: id=0 funktioniert nicht!!!!!
...
return TRUE; // return TRUE unless you set the focus to a control
}

void CWincehttpDlg::OnTimer(UINT nIDEvent)
{
static bool volatile s_bLocked = false;

if (!s_bLocked)
{
s_bLocked = true;
DoServer();
Sleep(100);
s_bLocked = false;
}

CDialog::OnTimer(nIDEvent);
}

void CWincehttpDlg::DoServer()
{
HWND hWnd = GetSafeHwnd();
int nPortNo = 4711;
int nTimeOutMs = 30000;
CString strRecv;

int nErr = CWinCESupport::StartServer(hWnd, nPortNo, nTimeOutMs, strRecv);

strRecv.Replace(TEXT("\n"), TEXT("\r\n"));
GetDlgItem(IDC_EDIT1)->SetWindowText(strRecv);
}