黑客编程弄的,MyTcpTran类
MyTcpTran.h
// MyTcpTran.h: interface for the CMyTcpTran class.
//
//
#if !defined(AFX_MYTCPTRAN_H__871B589A_093E_4E30_9E0D_943EA912FEBB__INCLUDED_)
#define AFX_MYTCPTRAN_H__871B589A_093E_4E30_9E0D_943EA912FEBB__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#define SOCKETBIND 1 //服务器监听端口 等待客户端连接
#define SOCKETNOBIND 2 //服务器主动链接客户端
#include
#include
using namespace std;
#pragma comment (lib,"ws2_32.lib")
class CMyTcpTran
{
public:
CMyTcpTran();
virtual ~CMyTcpTran();
public:
static BOOL InitSocketLibray(int lowver,int higver); //初始化 winsock api 链接库文件
public:
SOCKET InitSocket(int SocketType,string strBindIp,u_short BindPort,int opt);//初始化socket
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__871B589A_093E_4E30_9E0D_943EA912FEBB__INCLUDED_)
MyTcpTran.cpp
// MyTcpTran.cpp: implementation of the CMyTcpTran class.
//
//
#include "stdafx.h"
#include "CMyTcpTram.h"
#include "MyTcpTran.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//
// Construction/Destruction
//
/*
********************************************
CMyTcpTran类 完成TCP的通信
********************************************
*/
CMyTcpTran::CMyTcpTran()
{
m_Socket=INVALID_SOCKET; //默认返回 无效的套接字
}
CMyTcpTran::~CMyTcpTran()
{
}
/*
*****************************************
函数名:InitSocketLibray
功能:初始化SOCKET的通信库 要求winsockt 2
参数: lowver低版本;higver高版本
*****************************************
*/
BOOL CMyTcpTran::InitSocketLibray(int lowver,int higver)
{
WORD wVersion=0;
int erret=-1;
WSADATA wsaDate;
//wVersion=MAKEWORD(2,1); //2.1版本
wVersion=MAKEWORD(lowver,higver);
erret=WSAStartup(wVersion,&wsaDate);
//判断动态链接库对应的版本
if(LOBYTE(wsaDate.wVersion)!=2 ||
HIBYTE(wsaDate.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;
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*后
//将IP点数格式转化为无符号长整形
sockStruct.sin_addr.S_un.S_addr=inet_addr(strBindIp.c_str());
}
//将BindPort转化为网络字节序后保存
sockStruct.sin_port=htons(BindPort);
//不绑定端口
if(SocketType == SOCKETNOBIND)
{
//将sockStruct结构体所指定的网络上的计算机进行连接
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和端口 bind
if(bind(socketid,(SOCKADDR *)&sockStruct,sizeof(SOCKADDR_IN))==SOCKET_ERROR)
{
//绑定端口失效
closesocket(socketid);
socketid=INVALID_SOCKET;
}
else
{
//绑定ip和端口成功,监听来自网络其他计算机的连接队列
//SOMAXCONN等待最大连接队列
if(listen(socketid,SOMAXCONN)==SOCKET_ERROR)
{
//监听函数调用失败,关闭套接字,设置套接字为无效状态
closesocket(socketid);
socketid=INVALID_SOCKET;
}
}
m_Socket=socketid;
}
return socketid;
}
/*
*************************************
函数名:Myaccept
功能:创建一个新的套接字与参数addr指定的客户端套接字建立连接通信
参数:s: 处于监听状态的套接字
addr:新创建的套接字地址结构
addlen:新创建的套接字地址结构长度
返回值:调用失败 返回INVALID_SOCKET
调用成功 则返回成功的套接字
*************************************
*/
SOCKET CMyTcpTran::Myaccept(SOCKET s,struct sockaddr* addr,int* addrlen)
{
//新创建的套接字初始化为无效套接字
SOCKET accpsocket=INVALID_SOCKET;
//accept 调用成功可返回的套接字,失败返回INVALID_SOCKET
accpsocket=accept(s,addr,addrlen);
return accpsocket;
}
/*
**********************************************
函数名:Myrecv
功能:根据类型初始化SOCKET 资源
参数:sock:接收端套接字的描述
buf:用来存放接收数据的缓冲区
len:接收数据的大小
flag: 一般设置为0
overtime:超时时间
EndMark:结束标记
soonflag:是否立即返回
返回值:接收到数据的字节数
*********************************************8
*/
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 readfds; //fd_set文件描述的集合
struct timeval timeout;
timeout.tv_sec=0; //设置超时值
timeout.tv_usec=500; //tv_sec 秒 tv_usec微秒
DWORD s_time=GetTickCount(); //返回从操作系统启动到现在经过的毫秒数
while(nleft)
{
//接收消息
MSG msg;
PeekMessage(&msg,NULL,0,0,PM_REMOVE);
//接收的消息是退出的消息
if(msg.message==WM_QUIT)
return 0;
FD_ZERO(&readfds); //将set清零
FD_SET(sock,&readfds); //将fd放入set
//select 函数用来管理套接字的I/O,避免出现无辜锁定
if(select(0,&readfds,NULL,NULL,&timeout)==SOCKET_ERROR)
{
return SOCKET_ERROR;
}
DWORD e_time=GetTickCount();
if(!FD_ISSET(sock,&readfds)) FD_ISSET检查sock是否在这个集合里面
{
if(e_time-s_time>overtime*1000) //超时
return SOCKET_ERROR;
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;
}
/*
*************************************
函数名: mysend
功能: 用指定的SOCKET发送数据
参数: socket:发送端套接字描述符
buf:用来存放要发送数据的缓冲区
flag:一般置0
overtime:用来设置超时时间
返回值:实际发送数据的字节数
*************************************
*/
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("mesendEx 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 ret;
}