打造自己的TCP通信类

黑客编程弄的,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 <WINSOCK2.H>
#include <string>
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;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
使用 Visual Studio 打造一个简单的通信系统可以通过以下步骤实现: 1. 创建一个新的 Visual Studio 解决方案。可以选择 C# 作为主要开发语言。 2. 在解决方案中创建一个或多个项目,其中一个项目用于实现通信系统的主要功能。 3. 在主项目中创建一个用户界面,用于用户输入和接收消息。可以使用 Windows Forms 或 WPF 创建用户界面。 4. 添加必要的控件,例如文本框、按钮和列表框,以便用户可以输入和查看消息。 5. 创建一个用于处理通信相关的功能,例如发送和接收消息。可以使用 TCP 或 UDP 协议进行通信。 6. 使用适当的库或框架来实现网络通信功能。例如,可以使用 .NET 中的 Socket 或第三方库如 SignalR。 7. 实现发送消息的功能。当用户点击发送按钮时,获取文本框中的消息内容并将其发送给目标接收者。 8. 实现接收消息的功能。设置监听器以接收来自其他用户的消息,并显示在列表框中。 9. 添加其他必要的功能,例如用户身份验证、加密和文件传输等。这取决于通信系统的具体需求。 10. 对代码进行调试和测试,确保通信系统正常工作并能够达到预期效果。 11. 打包和部署通信系统。可以创建可执行文件或安装程序,以便其他用户可以在其计算机上运行该系统。 总结起来,使用 Visual Studio 创建一个简单的通信系统,需要创建一个用户界面,实现发送和接收消息的功能,并添加必要的通信功能和其他特性。最后,对系统进行测试和部署,确保其正常工作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值