SOCKET类——CMyTcpTran class

开发网络安全程序基础

// MyTcpTran.cpp: implementation of the CMyTcpTran class.
//
//////////////////////////////////////////////////////////////////////

#include "MyTcpTran.h"


//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CMyTcpTran::CMyTcpTran()
{
 //默认INVALID_SOCKET 嵌套字无效
 m_Socket = INVALID_SOCKET;
}

CMyTcpTran::~CMyTcpTran()
{

}

BOOL CMyTcpTran::InitSocketLibray(int lowver,int higver )
{
 WORD wVersion =0 ;
 int  errret = -1;
 WSADATA wsaData;
 
 //MAKEWORD 将两个BYTE类型合并为WORD型
 //高位字节指明副版本
 //低位字节指明主板本
 //如果使用2.1版本的SOCKET,则代码如下 wVersion=MAKEWORD(2,1)
 wVersion = MAKEWORD(lowver,higver);
 //加载和初始化SOCKET对应的动态链接库WS2_32.DLL的一些信息,为使用SOCKET做准备
 errret = WSAStartup(wVersion,&wsaData);
 
 if( LOBYTE( wsaData.wVersion) !=2 ||
  HIBYTE( wsaData.wVersion) !=2 )
 {
  MessageBox(NULL,"winsocket库版本低","提示",MB_OK);
  return FALSE;
 }
 
 return TRUE;
}

 

 

SOCKET CMyTcpTran::InitSocket( int SocketType, string strBindIp,u_short BindPort,int opt)
{
 //创建一个用于网络通信的套接字
 SOCKET socketid = INVALID_SOCKET;
 socketid = socket(PF_INET,SOCK_STREAM,0);
 SOCKADDR_IN sockStruct;
 //AF_INET使用TCP/IP协议
 sockStruct.sin_family = AF_INET;

 if( strBindIp.empty() )
 {
  //strBindIp为空,则INADDR_ANY  SOCKET能够接受任何IP的信息
  sockStruct.sin_addr.S_un.S_addr = INADDR_ANY;
  
 }else
 {
  //strBindIp不为空,则strBindIp char *后 转换为无符号长整型
  sockStruct.sin_addr.S_un.S_addr = inet_addr(strBindIp.c_str()); 
 }
   
 //将BindPort转换为网络字节后保存
    sockStruct.sin_port = htons(BindPort);

 //不绑定端口
 if( SocketType == SOCKETNOBIND )
 {
  //与所指定的计算机进行连接
  if(connect(socketid,(LPSOCKADDR)&sockStruct,sizeof(sockStruct)) == SOCKET_ERROR)
  {
   //OutputDebugString("连接错误!");
   //关闭已经打开的套接字 防止占用内存
   closesocket(socketid);
   shutdown(socketid,2);
   //设置套接字无效
   socketid = INVALID_SOCKET;
  }
  
  m_Socket = socketid;
  
 }
 //如果是绑定本地端口
 else if( SocketType == SOCKETBIND )
 {
  //绑定由sockStruct指定的网络计算机IP和端口
  if(bind(socketid,(sockaddr*)&sockStruct,sizeof(sockaddr_in)) == SOCKET_ERROR)
  {
   closesocket(socketid);
   socketid = INVALID_SOCKET;

  }
  else
  { 
   //绑定IP和端口成功,窃听来自网络其他计算机的连接队列
   if( listen(socketid,SOMAXCONN) == SOCKET_ERROR )
   {
    closesocket(socketid);
    socketid = INVALID_SOCKET;
   }
  }
  
  m_Socket = socketid;
 }
   
 return socketid;


SOCKET CMyTcpTran::myaccept(SOCKET s,struct sockaddr* addr,int* addrlen)
{
 //创建新的套接字并初始化为INVALID_SOCKET
 SOCKET accpsocket  = INVALID_SOCKET;
 //accept 调用成功返回可用的套接字,失败返回INVALID_SOCKET
 accpsocket = accept(s,addr,addrlen);
 return accpsocket;
}



int CMyTcpTran::myrecv(SOCKET sock, char *buf, int len, int flag , int overtime ,char*EndMark,BOOL soonflag)
{
 //定义变量 
 int  ret;
 int  nLeft = len;
 int  idx  = 0;
 int  nCount = 0;
 //fd_set 文件描述符集合
 fd_set readfds;
 struct timeval  timeout;
 //设置超时时间
 timeout.tv_sec = 0;
 timeout.tv_usec = 500;
 //返回从操作系统启动到现在经过的毫秒数
 DWORD s_time = GetTickCount();
 
 while ( nLeft > 0 )
 {
  //接收消息
  MSG msg;
  PeekMessage(&msg, NULL,  0, 0, PM_REMOVE) ;
  //如果接收到的信息为退出信息
  if(msg.message == WM_QUIT)
   return 0;
  
  //将SET清零
  FD_ZERO( &readfds );
  //将FD放入SET
  FD_SET( sock , &readfds );
  if( select( 0 , &readfds , NULL , NULL , &timeout ) == SOCKET_ERROR )
  {
   return SOCKET_ERROR;
  }
  
  DWORD e_time = GetTickCount( );
  if  ( !FD_ISSET( sock , &readfds ) )
  {
   if( e_time - s_time > overtime*1000 ) //超时
    return SOCKET_TIMEOUT;
   else
    continue;
  }
  
  ret = recv( sock, &buf[idx], nLeft, flag );//接收数据
  
  if( soonflag == TRUE )
  {
   //立即返回接收到的字节数
   return ret;
  }
  
  s_time = e_time ; // 只要有数据就重新置初始时间值
  
  if ( ret <= 0 )
  {
   //错误处理
   int  LastError = GetLastError();
   if ( ( -1 == ret ) && ( WSAETIMEDOUT   == LastError ) )
    continue;
   if ( ( -1 == ret ) && ( WSAEWOULDBLOCK   == LastError ) )
   {
    if ( nCount < 2000 )
    {
     Sleep( 10 );
     nCount++;
     continue;
    }
   }
   return ret;
  }
  nCount = 0;
  
  nLeft -= ret;
  idx  += ret;

  if( EndMark != NULL && idx>5)
  {
   if( strstr(buf+(idx-5),EndMark) != NULL )
   {
    break;
   }
  }
 }

 return idx;
}


int CMyTcpTran::mysend(SOCKET sock, const char *buf, int len, int flag,int overtime)
{
 //定义变量 
 int  ret;
 int  nLeft = len;
 int  idx  = 0;
 
 fd_set readfds;
 struct timeval  timeout;
 timeout.tv_sec = 0;
 timeout.tv_usec = 500;
 DWORD s_time = GetTickCount();
 
 while ( nLeft > 0 )
 {
  //向对话框发送关闭消息
  MSG msg;
  PeekMessage(&msg, NULL,  0, 0, PM_REMOVE) ;
  if(msg.message == WM_QUIT)
   return 0;
  
  FD_ZERO( &readfds );
  FD_SET( sock , &readfds );
  
  int errorret   = select( 0 , NULL, &readfds, NULL , &timeout );
  
  if( errorret == SOCKET_ERROR )
  {
   OutputDebugString("mysendEx SOCKET 错误");
   return SOCKET_ERROR;
  }
  //计算当前时间
  DWORD e_time = GetTickCount( );
  if  ( !FD_ISSET( sock , &readfds ) )
  {
   //如果超时,返回
   if( e_time - s_time > overtime*1000 )
   {
    
    OutputDebugString("mysendEx发送数据超时");
    return 0;
   }
   else
   {
    //OutputDebugString("发送数据FD_ISSET 超时");
    continue;
   }
  }
  
  ret = send( sock, &buf[idx], nLeft, flag );  
  if ( ret <= 0 )
  {
   return ret;
  } 
  nLeft -= ret;
  idx  += ret;
 }
 
 return len;
}

 

// MyTcpTran.h: interface for the CMyTcpTran class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_MYTCPTRAN_H__98D1E493_C9EA_4E23_AB2C_0BA8907888EB__INCLUDED_)
#define AFX_MYTCPTRAN_H__98D1E493_C9EA_4E23_AB2C_0BA8907888EB__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#define SOCKETBIND 1
#define SOCKETNOBIND 2
#define SOCKET_TIMEOUT -100

#include "winsock2.h"
#include <string.h>
#include <iostream>
using namespace std;
#pragma comment (lib,"ws2_32.lib")

class CMyTcpTran 
{
public:
 CMyTcpTran();
 virtual ~CMyTcpTran();

public:
 static BOOL InitSocketLibray(int lowver,int higver);

public:
 SOCKET InitSocket( int SocketType, string strBindIp,u_short BindPort,int opt);
 SOCKET myaccept(SOCKET s,struct sockaddr* addr,int* addrlen);
 int  mysend(SOCKET sock, const char *buf, int len, int flag,int overtime);
 int  myrecv(SOCKET sock, char *buf, int len, int flag , int overtime,char*EndMark,BOOL soonflag=FALSE); 

private:
 SOCKET m_Socket;

};

#endif // !defined(AFX_MYTCPTRAN_H__98D1E493_C9EA_4E23_AB2C_0BA8907888EB__INCLUDED_)

你可能感兴趣的:(SOCKET类——CMyTcpTran class)