封装TCP类
为田东等地区用户提供了全套网页设计制作服务,及田东网站建设行业解决方案。主营业务为成都做网站、网站设计、外贸营销网站建设、田东网站设计,以传统方式定制建设网站,并提供域名空间备案等一条龙服务,秉承以专业、用心的态度为用户提供真诚的服务。我们深信只要达到每一位用户的要求,就会得到认可,从而选择与我们长期合作。这样,我们也可以走得更远!
封装一下tcp类, 步骤还可以简化,
直接放上代码类名:XTCP
xtcp.h
#ifndef _XTCP_H_ #define _XTCP_H_ #include#include class XTCP { public: XTCP(); virtual ~XTCP(); public: int CreateSocket();//创建socket 反悔socket bool Bind(unsigned short port);//绑定端口 XTCP Accept();//反回一个对象 void Close();//关闭 主动做 int Recv(char *buf, int bufsize);//接收 int Send(const char *buf, int sendsize);//发送 int m_sock = 0; unsigned short m_port = 0; std::string ip; }; #endif //_XTCP_H_
xtcp.cpp
#include "XTCP.h" #ifdef WIN32 #include#define socklen_t int #else #include #include #include #include #define closesocket close #include #endif XTCP::XTCP() { #ifdef WIN32 static bool first = true; //保证只进入一次 if (first) { first = false; WSADATA ws; WSAStartup(MAKEWORD(2, 2), &ws); } #endif } XTCP::~XTCP() { } int XTCP::CreateSocket() { m_sock = socket(AF_INET, SOCK_STREAM, 0); if (m_sock == -1) { printf("create socket failed!\n"); } return m_sock; } bool XTCP::Bind(unsigned short port) { sockaddr_in sa; sa.sin_family = AF_INET; sa.sin_port = htons(port); sa.sin_addr.s_addr = htonl(0); if (bind(m_sock, (sockaddr*)&sa, sizeof(sa))) { printf("bind port err\n"); //绑定成功 return false; } //侦听 listen(m_sock, 10); //绑定失败 return true; } void XTCP::Close() { if (m_sock <= 0) return; closesocket(m_sock); } XTCP XTCP::Accept() { XTCP tcp; sockaddr_in sadd; socklen_t len = sizeof(sadd); printf("lsiteb ... accept ok\n"); //这里会阻塞 只有等待有新的连接 才会执行下面的代码 int client = accept(m_sock, (sockaddr*)&sadd, &len); //反悔判断m_sock是否为0就行了 if (client <= 0)return tcp; printf("client connect ok\n"); //输出端口号和信息 tcp.ip = inet_ntoa(sadd.sin_addr); //网络字节序转本地字节序哦 tcp.m_port = ntohs(sadd.sin_port); //记录socket tcp.m_sock = client; printf("IP: %s:port: %d\n", tcp.ip.c_str(), tcp.m_port); return tcp; } int XTCP::Recv(char *buf, int bufsize) { return recv(m_sock, buf, bufsize, 0); } int XTCP::Send(const char *buf, int sendsize) { //buf 必须发送制定大小 保证发送全部成功 int s = 0; //以发送的 发送大小减去以及发送的 while (s != sendsize) { //反回就是发送的长度 int len = send(m_sock, buf + s, sendsize - s, 0); if (len <= 0) break; s += len; //加上发送的长度 } return s; }
测试代码
#include "XTCP.h" #includeclass TcpThread { public: //线程入口函数 创建一个 void Main() { char buf[1024]; for (;;) { memset(buf, 0, sizeof(buf)); int recv_len = client.Recv( buf, sizeof(buf) - 1); if (recv_len <= 0)break; if (strstr(buf, "quit") != NULL) { char re[] = "quit success\n"; int sendlen = client.Send(re, strlen(re) + 1); break; } char *p_ok = "ok\n"; int sendlen = client.Send(p_ok,strlen(p_ok)); printf("recv %s\n", buf); } client.Close(); delete this; } //用户的socket XTCP client; }; int main(int argc,char*argv[]) { unsigned short port = 8016; XTCP mytcp; //创建 mytcp.CreateSocket(); //绑定 if (!mytcp.Bind(port)) return -1; for (;;) { XTCP client = mytcp.Accept(); //创建线程 TcpThread *th = new TcpThread(); th->client = client; std::thread sthr(&TcpThread::Main, th); // 释放主线程占用的资源 sthr.detach(); } mytcp.Close(); getchar(); return 0; }
原理就是: 创建一个对象XTCP server,有一个int变量,是用来记录创建的socket.的,他用来和用户建立连接,然后服务器必须要绑定端口,Bind里自动侦听。(调用了listen函数)
然后就是反回一个用户client的XTCP对象,把这个对象赋值给上面
的线程类里的成员,应为他TcpThread*th = new TcpThread();
他里面有一个th->client = client; 把他赋值给这个client.
然后创建线程在线程里等待数据收发, 这个new的对象 是在
线程函数里进行释放的 也就是closesocket后面有一个delete this. ,最后就是th->detach() 是释放主线程占用的子线程
的资源,。
移植到linux
先看下makefile
SRC 添加main.cpp 和 XTCP.cpp 就行了
CC=g++ SRC=main.cpp XTCP.cpp OBJ=hello.o EXEC=manc start: $(CC) $(SRC) -o $(EXEC) -std=c++11 -lpthread $(OBJ): $(CC) $(OBJ) -c $(SRC) clean: rm -f $(OBJ) $(EXEC) run: ./$(EXEC)
执行make start 编译连接
执行make run 执行
成功并发,多个客户端
封装TCP类到Windowsd的dll动态库
将一个类封装到dll和linux的so
在这个博客里讲:
http://12158490.blog.51cto.com/12148490/1947885