非阻塞 TCP协议下多用户的服务器

来源:互联网 发布:深度linux系统写python 编辑:程序博客网 时间:2024/06/05 15:27
// 一个监听线程, 每当一个新的客户端连接进来时会再创建一个新的线程供连接
#include "stdafx.h"
#include <winsock2.h>
#include <iostream>
#pragma comment( lib, "ws2_32.lib" )

const static int BUF_SIZE = 256;
using namespace std;

#define MAIN_RETURN_ERROR   -1;
#define MAIN_RETURN_NORMAL  0;

DWORD WINAPI AnswerThread( LPVOID lparam );

sockaddr_in addrClient;
int addrClientLen = sizeof( addrClient );

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 ;
     }

      // 通过WinSock 实现网络通信
      SOCKET sServer ;
    // 创建用于监听的Socket
      sServer = socket ( AF_INET, SOCK_STREAM, IPPROTO_TCP );
      if( INVALID_SOCKET == sServer )
     {
           cout<<"Socket Failed !" <<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 ( sServer, ( const struct sockaddr *)&addrServ , sizeof( SOCKADDR_IN ) );
      if( SOCKET_ERROR == retVal )
     {
           cout<<"bind failed !" <<endl;
           closesocket( sServer );
           WSACleanup();
           return -1;
     }

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

      // 设置socket 其为非阻塞模式 , argp 设为非零值
      int iModel = 1; 
      retVal = ioctlsocket ( sServer, FIONBIO, (u_long FAR* )&iModel );
      if( SOCKET_ERROR == retVal )
     {
           cout<<"ioctlsocket failed " <<endl;
           WSACleanup();
           return MAIN_RETURN_ERROR ;
     }

      cout<<"TCP Server Start ... ..." <<endl;
      // 循环等待
      while( true )
     {
           SOCKET sClient = accept( sServer, ( sockaddr FAR*)&addrClient , &addrClientLen );
           if( INVALID_SOCKET == sClient )
          {
               int err = WSAGetLastError();
               if( WSAEWOULDBLOCK == err  // 没接到连接请求
              {
                    Sleep( 100 );
                    continue;
              }
               else
              {
                    cout<<"accept failed" <<endl;
                    closesocket( sServer );
                    WSACleanup();
                    return MAIN_RETURN_ERROR ;
              }
          }

          // 接到了创建一个新线程供新的客户端使用
           DWORD dwThreadId ;
           CreateThread( NULL , NULL, AnswerThread, (LPVOID )sClient, 0, & dwThreadId );
     }

      // 最后做一些清理工作
      closesocket( sServer );
      WSACleanup();
      system("pause" );
      return MAIN_RETURN_NORMAL ;
}

DWORD WINAPI AnswerThread( LPVOID lparam )
{
      // 循环接受客户端发送来的请求,直到客户端发送 quit 命令
      char buf [BUF_SIZE];
      int  retVal ;
      SOCKET sClient = (SOCKET)( LPVOID)lparam ;
      while( true )
     {
           ZeroMemory( buf , BUF_SIZE );
           retVal = recv ( sClient, buf, BUF_SIZE , 0 );

           if( SOCKET_ERROR == retVal )
          {
               int err = WSAGetLastError();
               if( WSAEWOULDBLOCK == err )
              {
                    Sleep( 100 );
                    continue;
              }
               else if ( WSAETIMEDOUT == err || WSAENETDOWN == err )   // 网络系统故障
              {
                    cout<<"recv failed !" <<endl;
                    closesocket( sClient );
                    WSACleanup();
                    return MAIN_RETURN_ERROR ;
              }
          }

           SYSTEMTIME st ;
           GetLocalTime( &st );
           char sDateTime [30];
           sprintf( sDateTime , "%4d-%2d-%2d %2d:%2d:%2d", st.wYear , st. wMonth, st .wDay, st.wHour , st. wMinute, st.wSecond );
           cout<<sDateTime <<"  , Recv From Client [ "<< inet_ntoa( addrClient .sin_addr )<<":" <<addrClient. sin_port<<"]: " <<buf<< endl;

           if( 0 == strcmp ( buf, "quit" ) )
          {
               retVal = send ( sClient, "quit", strlen ("quit"), 0 );
               break;
          }
           else
          {
               char msg [BUF_SIZE];
               sprintf( msg , "Message receive - %s ", buf );
               while( true )
              {
                    retVal = send ( sClient, msg, strlen ( msg ), 0 );
                    if( SOCKET_ERROR == retVal )
                   {
                         int err = WSAGetLastError();
                         if( WSAEWOULDBLOCK == err )
                        {
                              Sleep( 100 );
                              continue;
                        }
                         else
                        {
                              cout<<"send failed !" <<endl;
                              closesocket( sClient );
                              WSACleanup();
                              return MAIN_RETURN_ERROR ;
                        }
                   }
                    else
                         break;
              }
          }
     }

      closesocket( sClient );
}
0 0
原创粉丝点击