Windows IO模型 2 通过历程完成 服务器

来源:互联网 发布:js 鼠标点击改变样式 编辑:程序博客网 时间:2024/06/17 14:34
#include "stdafx.h"
#include <winsock2.h>
#include <iostream>
#pragma comment( lib, "ws2_32.lib" )

using namespace  std;

#define   MSGSIZE 1024
SOCKET    g_sNewClientConnection;
BOOL      g_bNewConnectionArrived = FALSE;

struct PER_IO_OPERATION_DATA
{
      WSAOVERLAPPED overlap ;               // 重叠结构体
      WSABUF        Buffer;                // 缓冲对象
      char          szMessage[ MSGSIZE];    // 缓冲区字符对象

      DWORD         NumberOfBytesRecvd;    // 接受字节位
      DWORD         Flags;                 // 标识位
      SOCKET        sClient;               // Socket
};

typedef PER_IO_OPERATION_DATA* LPPER_IO_OPERATION_DATA ;

enum
{
      MAIN_RETURN_ERROR           =  -1,
      MAIN_RETURN_NORMAL          =   0,
};

void CALLBACK CompletionROUTINE( DWORD dwError, DWORD cbTransferred , LPWSAOVERLAPPED lpOverlapped, DWORD dwFlags )
{
      LPPER_IO_OPERATION_DATA lpPerIOData = ( LPPER_IO_OPERATION_DATA )lpOverlapped;

      if( dwError != 0 || cbTransferred == 0 )
     {
           closesocket( lpPerIOData ->sClient );
           HeapFree( GetProcessHeap (), 0, lpPerIOData );
     }
      else
     {
           lpPerIOData->szMessage [cbTransferred] = '\0';
           // 向客户端发送数据
           send( lpPerIOData ->sClient, lpPerIOData ->szMessage, cbTransferred, 0 );
           memset( &lpPerIOData ->overlap, 0, sizeof (WSAOVERLAPPED) );

           lpPerIOData->Buffer .len = MSGSIZE;
           lpPerIOData->Buffer .buf = lpPerIOData ->szMessage;
           WSARecv( lpPerIOData ->sClient, &lpPerIOData ->Buffer, 1, &lpPerIOData ->NumberOfBytesRecvd,
              & lpPerIOData->Flags , &lpPerIOData-> overlap, CompletionROUTINE );

           cout<<lpPerIOData ->Buffer. buf<<endl ;
     }
}


DWORD WINAPI WorkThread( LPVOID lpParam )
{
      LPPER_IO_OPERATION_DATA lpPerIOData = NULL;
      while( TRUE )
     {
           if( g_bNewConnectionArrived  // 如果有新的请求
          {
               lpPerIOData = (LPPER_IO_OPERATION_DATA )HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY , sizeof( PER_IO_OPERATION_DATA ) );

               lpPerIOData->Buffer .len = MSGSIZE;
               lpPerIOData->Buffer .buf = lpPerIOData ->szMessage;
               lpPerIOData->sClient     = g_sNewClientConnection ;

               WSARecv( lpPerIOData ->sClient, &lpPerIOData ->Buffer, 1, &lpPerIOData ->NumberOfBytesRecvd,
                       & lpPerIOData->Flags ,   &lpPerIOData ->overlap, CompletionROUTINE );
               g_bNewConnectionArrived = FALSE;

               cout<<lpPerIOData ->Buffer. buf<<endl ;

          }

           SleepEx( 1000, TRUE );
     }

      return 0;
}

int _tmain( int argc , _TCHAR* argv[])
{
      // 初始化Winsock 2.2
      WSADATA wsaData ;
      if( WSAStartup ( MAKEWORD( 2, 2 ), & wsaData ) != 0 )
     {
           cout<<"WSAStartup 无法初始化 !" <<endl ;
           return MAIN_RETURN_ERROR ;
     }

      SOCKET ListenSocket ;
      ListenSocket = WSASocket ( AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED );
      if( INVALID_SOCKET == ListenSocket )
     {
           cout<<"Socket Failed !" <<" Reson:"<< WSAGetLastError ()<<endl ;
           WSACleanup();
           return MAIN_RETURN_ERROR ;
     }

      // 设置服务器Socket 地址
      SOCKADDR_IN addrServ ;
      addrServ.sin_family    = AF_INET;
      addrServ.sin_port      = htons( 9990 );   // 服务器端口号
      addrServ.sin_addr .S_un. S_addr = htonl ( INADDR_ANY );

      // 绑定
      int    retVal ;
      retVal = bind ( ListenSocket, ( const struct sockaddr *)&addrServ , sizeof( SOCKADDR_IN ) );
      if( SOCKET_ERROR == retVal )
     {
           cout<<"bind failed !" <<"   Reson: "<< WSAGetLastError ()<<endl ;
           closesocket( ListenSocket );
           WSACleanup();
           return -1;
     }

      // 监听
      retVal = listen ( ListenSocket, 3 );
      if( SOCKET_ERROR == retVal )
     {
           cout<<"listen failed !" <<" Reson:"<< WSAGetLastError ()<<endl ;
           closesocket( ListenSocket );
           WSACleanup();
           return -1;
     }

      DWORD dwThreadId ;
      CreateThread( NULL , 0, WorkThread, NULL, 0, &dwThreadId );

      // 循环接受客户端请求
      sockaddr_in addrClient ;
      int addrClientLen = sizeof( addrClient );
      while( TRUE )
     {
           g_sNewClientConnection   = accept( ListenSocket, (struct sockaddr *)& addrClient, &addrClientLen );
           g_bNewConnectionArrived = TRUE;
           cout<<"Accept Client: "<< inet_ntoa(addrClient .sin_addr)<< " : "<< ntohs(addrClient .sin_port)<< endl;
     }

      closesocket(ListenSocket );
      closesocket(g_sNewClientConnection );
      system("pause" );
      return 0;
}
  







0 0
原创粉丝点击