socket服务器端代码实例

 

下面就是源代码,其中部分很基本的代码我就省略掉了,编译平台为
Win2000 Server with SP2 + VC6.0 with SP5

#include <windows.h>
#include <winsock2.h>

#define PORT 5150
#define DATA_BUFSIZE 8192

typedef struct _SOCKET_INFORMATION {
 BOOL RecvPosted;
 CHAR Buffer[DATA_BUFSIZE];
 WSABUF DataBuf;
 SOCKET Socket;
 DWORD BytesSEND;
 DWORD BytesRECV;
 _SOCKET_INFORMATION *Next;
} SOCKET_INFORMATION, * LPSOCKET_INFORMATION;

#define WM_SOCKET (WM_USER + 1)

void CreateSocketInformation(SOCKET s, HWND);
LPSOCKET_INFORMATION GetSocketInformation(SOCKET s);
void FreeSocketInformation(SOCKET s);

LPSOCKET_INFORMATION SocketInfoList;

LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
    
LPSTR lpCmdLine, int nCmdShow)
{
 DWORD Ret;
 SOCKET Listen;
 SOCKADDR_IN InternetAddr;
 WSADATA wsaData;
 static TCHAR szAppName[] = TEXT ("HelloWin") ;
 HWND hwnd ;
 MSG msg ;
 WNDCLASS wndclass ;

 // Prepare echo server
 wndclass.style = CS_HREDRAW | CS_VREDRAW ;
 ...
 ...
 RegisterClass (&wndclass);
 hwnd = CreateWindow (...) ; // creation parameters
 ShowWindow (hwnd, nCmdShow) ;
 UpdateWindow (hwnd) ;

 if ((Ret = WSAStartup(0x0202, &wsaData)) != 0)
 {
  MessageBox(hwnd, TEXT("Start socket failed"), TEXT("error"), MB_OK);
  ExitProcess(1);

 }
 if ((Listen = socket (PF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
 {
  MessageBox(hwnd, TEXT("socket() failed"), TEXT("error"), MB_OK);
  ExitProcess(1);

 
}
 WSAAsyncSelect(Listen, hwnd, WM_SOCKET, FD_ACCEPT|FD_CLOSE);
 InternetAddr.sin_family = AF_INET;
 InternetAddr.sin_addr.s_addr = htonl(INADDR_ANY);
 InternetAddr.sin_port = htons(PORT);

 if (bind(Listen, (PSOCKADDR) &InternetAddr, sizeof(InternetAddr))
    == SOCKET_ERROR)
 {
  MessageBox(hwnd, TEXT("bind() failed"), TEXT("error"), MB_OK);
  ExitProcess(1);
 }
 if (listen(Listen, 5))
 {
  MessageBox(hwnd, TEXT("listen() failed"), TEXT("error"), MB_OK);
  ExitProcess(1);

 
}
 // Translate and dispatch window messages for the application thread
 while (GetMessage (&msg, NULL, 0, 0))
 {
  TranslateMessage (&msg) ;
  DispatchMessage (&msg) ;
 }
 return msg.wParam ;
}

LRESULT CALLBACK WndProc (HWND hwnd, UINT message,
        
WPARAM wParam, LPARAM lParam)
{
 HDC hdc ;
 PAINTSTRUCT ps ;
 RECT rect ;
 SOCKET Accept;
 LPSOCKET_INFORMATION SocketInfo;
 DWORD RecvBytes, SendBytes;
 DWORD Flags;

 switch (message)
 {
  case WM_CREATE:
   return 0 ;

  case WM_PAINT:
   hdc = BeginPaint (hwnd, &ps) ;
   GetClientRect (hwnd, &rect) ;
   DrawText (hdc, TEXT ("Server Started!"), -1, &rect,
   DT_SINGLELINE | DT_CENTER | DT_VCENTER) ;
   EndPaint (hwnd, &ps) ;
   return 0 ;

  case WM_DESTROY:
   PostQuitMessage (0) ;
   return 0 ;

  case WM_SOCKET:
   if (WSAGETSELECTERROR(lParam))
   {
    MessageBox(...);
    FreeSocketInformation(wParam);
   }
   else
   {
    switch(WSAGETSELECTEVENT(lParam))
    {
     case FD_ACCEPT:
      if ((Accept = accept(wParam, NULL, NULL)) == INVALID_SOCKET)
      {
       MessageBox(...);
       break;
      }
      // Create a socket information structure to associate with the
      // socket for processing I/O.
      CreateSocketInformation(Accept, hwnd);
      WSAAsyncSelect(Accept, hwnd, WM_SOCKET,
         FD_READ|FD_WRITE|FD_CLOSE);
      break;

     case FD_READ:
      SocketInfo = GetSocketInformation(wParam);
      // Read data only if the receive buffer is empty.
      if (SocketInfo->BytesRECV != 0)
      {
       SocketInfo->RecvPosted = TRUE;
       return 0;
      }
      else
      {
       SocketInfo->DataBuf.buf = SocketInfo->Buffer;
       SocketInfo->DataBuf.len = DATA_BUFSIZE;
       Flags = 0;
       if (WSARecv(SocketInfo->Socket, &(SocketInfo->DataBuf),
           1, &RecvBytes, &Flags, NULL, NULL) == SOCKET_ERROR)
       {
        if (WSAGetLastError() != WSAEWOULDBLOCK)
        {
         MessageBox(...);
         FreeSocketInformation(wParam);
         return 0;
        }
       }
       else // No error so update the byte count
        SocketInfo->BytesRECV = RecvBytes;
      }
      // DO NOT BREAK HERE SINCE WE GOT A SUCCESSFUL RECV.
      // Go ahead and begin writing data to the client.

      case FD_WRITE:
       SocketInfo = GetSocketInformation(wParam);
       if (SocketInfo->BytesRECV > SocketInfo->BytesSEND)
       {
        SocketInfo->DataBuf.buf =
         SocketInfo->Buffer + SocketInfo->BytesSEND;
        SocketInfo->DataBuf.len =
         SocketInfo->BytesRECV - SocketInfo->BytesSEND;
        if (WSASend(SocketInfo->Socket, &(SocketInfo->DataBuf),
            1, &SendBytes, 0,NULL, NULL) == SOCKET_ERROR)
        {
         if (WSAGetLastError() != WSAEWOULDBLOCK)
         {
          MessageBox(...);
          FreeSocketInformation(wParam);
          return 0;
         }
        }
        else // No error so update the byte count
         SocketInfo->BytesSEND += SendBytes;
       }

       if (SocketInfo->BytesSEND == SocketInfo->BytesRECV)
       {
        SocketInfo->BytesSEND = 0;
        SocketInfo->BytesRECV = 0;
        // If a RECV occurred during our SENDs then we need to post
        // an FD_READ notification on the socket.

        if (SocketInfo->RecvPosted == TRUE)
        {
         SocketInfo->RecvPosted = FALSE;
         PostMessage(hwnd, WM_SOCKET, wParam, FD_READ);
        }
       }
       if(SocketInfo->DataBuf.buf != NULL)
        MessageBox(hwnd, SocketInfo->DataBuf.buf,
           TEXT("Received"), MB_OK);
       break;

      case FD_CLOSE:
       FreeSocketInformation(wParam);
       break;
    }
   }
   return 0;
 }
 return DefWindowProc(hwnd, message, wParam, lParam);
}


void CreateSocketInformation(SOCKET s, HWND hwnd)
{
 LPSOCKET_INFORMATION SI;
 if ((SI = (LPSOCKET_INFORMATION) GlobalAlloc(GPTR,
 sizeof(SOCKET_INFORMATION))) == NULL)
 {
  MessageBox(...);
  return;
 }
 // Prepare SocketInfo structure for use.
 SI->Socket = s;
 SI->RecvPosted = FALSE;
 SI->BytesSEND = 0;
 SI->BytesRECV = 0;
 SI->Next = SocketInfoList;
 SocketInfoList = SI;
}

LPSOCKET_INFORMATION GetSocketInformation(SOCKET s)
{
 SOCKET_INFORMATION *SI = SocketInfoList;
 
while(SI)
 {
  if (SI->Socket == s)
  return SI;
  SI = SI->Next;
 }
 return NULL;
}

void FreeSocketInformation(SOCKET s)
{
 SOCKET_INFORMATION *SI = SocketInfoList;
 SOCKET_INFORMATION *PrevSI = NULL;
 while(SI)
 {
  if (SI->Socket == s)
  {
   if (PrevSI)
    PrevSI->Next = SI->Next;
   else
    SocketInfoList = SI->Next;
   closesocket(SI->Socket);
   GlobalFree(SI);
   return;
  }
  PrevSI = SI;
  SI = SI->Next;
 }
}

服务器就这样建好了,只需要一个客户机就可以通信了,具体的代码我就不再贴了,各位可
以自己设计客户机,或者去下载区下载源程序。最后向大家推荐《Windows网络编程技术》,
真的不错。

本文中部分内容翻译自MSDN,客户机程序使用的是《Windows网络编程技术》中的例子

你可能感兴趣的:(socket,server,服务器,null,callback,structure)