C++socket网络编程(跨平台)实战HTTP服务器(三)
? ? ? ? ?????封裝TCP類
封裝一下tcp類, 步驟還可以簡化,
直接放上代碼類名:XTCP
xtcp.h
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | #ifndef?_XTCP_H_ #define?_XTCP_H_ #include?<iostream> #include?<string.h> 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
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 | #include?"XTCP.h" #ifdef?WIN32 #include?<Windows.h> #define?socklen_t?int #else #include?<sys/types.h> #include?<sys/socket.h> #include?<unistd.h> #include?<arpa/inet.h> #define?closesocket?close #include?<string.h> #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; } |
測試代碼
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | #include?"XTCP.h" #include?<thread> class?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 就行了
| 1 2 3 4 5 6 7 8 9 10 11 12 | 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
?本文轉自超級極客51CTO博客,原文鏈接:http://blog.51cto.com/12158490/1947886,如需轉載請自行聯系原作者
總結
以上是生活随笔為你收集整理的C++socket网络编程(跨平台)实战HTTP服务器(三)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Pycharm使用详解
- 下一篇: c++多态性