Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1501199
  • 博文数量: 218
  • 博客积分: 6394
  • 博客等级: 准将
  • 技术积分: 2563
  • 用 户 组: 普通用户
  • 注册时间: 2008-02-08 15:33
个人简介

持之以恒

文章分类

全部博文(218)

文章存档

2013年(8)

2012年(2)

2011年(21)

2010年(55)

2009年(116)

2008年(16)

分类: 网络与安全

2010-01-03 15:18:45

//////////////////////////////////////////////////////////////////////////
/// WSAAsyncSelect模型(同步I/O模型)
///这里为什么说他是同步的,就是因为实际的数据的Copy是同步进行///的,而不是异步的,只是相应的通知机制(通知数据已经准备好了),///是异步的
/// 这个模型允许应用程序以Windows消息的形式可在一个套接字上,接收网络事件通知
/// 具体的做法是在建好一个套接字后,调用WSAAsyncSelect函数。
/// 在我看来,WSAAsyncSelect是最简单的一种Winsock I/O模型(之所以说它简单是
/// 因为一个主线程就搞定了)。
/// 这里,我们需要做的仅仅是:
/// 1.在WM_CREATE消息处理函数中,初始化Windows Socket library,创建监听套接字,绑定,
///   监听,并且调用WSAAsyncSelect函数表示我们关心在监听套接字上发生的FD_ACCEPT事件;
/// 2.自定义一个消息WM_SOCKET,一旦在我们所关心的套接字(监听套接字和客户端套接字)上
///   发生了某个事件,系统就会调用WndProc并且message参数被设置为WM_SOCKET;
/// 3.在WM_SOCKET的消息处理函数中,分别对FD_ACCEPT、FD_READ和FD_CLOSE事件进行处理;
/// 4.在窗口销毁消息(WM_DESTROY)的处理函数中,我们关闭监听套接字,清除Windows Socket library
//////////////////////////////////////////////////////////////////////////
/// 老陈:服务器应用程序,微软:服务器操作系统
/// 老陈使用了微软公司的新式信箱。这种信箱非常先进,一旦信箱里有新的信件,盖茨就会给
/// 老陈打电话:喂,大爷,你有新的信件了!从此,老陈再也不必频繁上下楼检查信箱了,牙
//  也不疼了,你瞅准了,蓝天......不是,微软......
/// 微软提供的WSAAsyncSelect模型就是这个意思。 
//////////////////////////////////////////////////////////////////////////
/// The WSAAsyncSelect function requests Windows message-based notification of network
/// events for a socket.
//////////////////////////////////////////////////////////////////////////

#pragma once
#include <winsock.h>
#include <tchar.h>
#define PORT 5150
#define MSGSIZE 1024
#define WM_SOCKET WM_USER+0
#pragma comment(lib, "ws2_32.lib")
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{
 static TCHAR szAppName[] = _T("AsyncSelect Model");
 HWND hwnd ;
 MSG msg ;
 WNDCLASS wndclass ;
 wndclass.style = CS_HREDRAW | CS_VREDRAW ;
 wndclass.lpfnWndProc = WndProc ;
 wndclass.cbClsExtra = 0 ;
 wndclass.cbWndExtra = 0 ;
 wndclass.hInstance = hInstance ;
 wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
 wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
 wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
 wndclass.lpszMenuName = NULL ;
 wndclass.lpszClassName = szAppName ;
 if (!RegisterClass(&wndclass))
 {
  MessageBox (NULL, TEXT ("This program requires Windows NT!"), szAppName, MB_ICONERROR) ;
  return 0 ;
 }
 hwnd = CreateWindow (szAppName,
// window class name

  TEXT ("AsyncSelect Model"),
// window caption

  WS_OVERLAPPEDWINDOW,
// window style

  CW_USEDEFAULT,
// initial x position

  CW_USEDEFAULT,
// initial y position

  CW_USEDEFAULT,
// initial x size

  CW_USEDEFAULT,
// initial y size

  NULL,
// parent window handle

  NULL,
// window menu handle

  hInstance,
// program instance handle

  NULL) ;
// creation parameters

 ShowWindow(hwnd, iCmdShow);
 UpdateWindow(hwnd);
 while (GetMessage(&msg, NULL, 0, 0))
 {
  TranslateMessage(&msg) ;
  DispatchMessage(&msg) ;
 }
 return msg.wParam;
}
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
 WSADATA wsd;
 static SOCKET sListen;
 SOCKET sClient;
 SOCKADDR_IN local, client;
 int ret, iAddrSize = sizeof(client);
 char szMessage[MSGSIZE];
 switch (message)
 {
 case WM_CREATE:
  
// Initialize Windows Socket library

  WSAStartup(0x0202, &wsd);
  
// Create listening socket

  sListen = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  
// Bind

  local.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
  local.sin_family = AF_INET;
  local.sin_port = htons(PORT);
  bind(sListen, (struct sockaddr *)&local, sizeof(local));
  
// Listen

  listen(sListen, 3);
  
// Associate listening socket with FD_ACCEPT event

  WSAAsyncSelect(sListen, hwnd, WM_SOCKET, FD_ACCEPT);
  return 0;
 case WM_DESTROY:
  closesocket(sListen);
  WSACleanup();
  PostQuitMessage(0);
  return 0;
 case WM_SOCKET:
  if (WSAGETSELECTERROR(lParam))
  {
   closesocket(wParam);
   break;
  }
  switch (WSAGETSELECTEVENT(lParam))
  {
  case FD_ACCEPT:
   
// Accept a connection from client

   sClient = accept(wParam, (struct sockaddr *)&client, &iAddrSize);
   
// Associate client socket with FD_READ and FD_CLOSE event

   WSAAsyncSelect(sClient, hwnd, WM_SOCKET, FD_READ | FD_CLOSE);
   break;
  case FD_READ:
   ret = recv(wParam, szMessage, MSGSIZE, 0);
   if (ret == 0 || ret == SOCKET_ERROR && WSAGetLastError() == WSAECONNRESET)
   {
    closesocket(wParam);
   }
   else
   {
    szMessage[ret] = '\0';
    send(wParam, szMessage, strlen(szMessage), 0);
   }
   break;
  case FD_CLOSE:
   closesocket(wParam);
   break;
  }
  return 0;
 }
 return DefWindowProc(hwnd, message, wParam, lParam);
}


阅读(5341) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~