封装naive socket
周五去一个公司打了个酱油,面试官问我:你封装过socket没?
言下之意是问我实际写过底层代码没,我悻悻地说写过点。
PS:说实话木有封装过,今天无聊就来封装下。
话说写了这么久C++,底层用c来写还是灰常爽的,C++把它包起来很好看而且好用。
嗯嗯,言归正传,创建了MyTCPSocket:
问题记录1:一旦来了新的链接,就创建一个work线程来处理,但是遇到了小问题:
#pragma once #include <winsock.h> #include <stdio.h> #pragma comment(lib, "ws2_32.lib") static DWORD WINAPI WorkerFun(LPVOID aData); class MyTCPSocket { public: MyTCPSocket(void); ~MyTCPSocket(void); bool Init(); bool UnInit(); bool CreateSocket(); bool Bind(unsigned aPost,const char* aAdress); bool Listen(int aBacklog=5); bool Connect(unsigned aPost,const char* aAdress); bool Send(const char* aBuf); bool Recv(); void Accept(); private: SOCKET m_Socket; SOCKET m_ClientSocket; sockaddr_in m_SockClientaddrIn ; }; #include "MyTCPSocket.h" MyTCPSocket::MyTCPSocket(void) :m_Socket(INVALID_SOCKET) { } MyTCPSocket::~MyTCPSocket(void) { } bool MyTCPSocket::Init() { int iResult; WORD wVersionRequested; WSADATA wsaData; wVersionRequested = MAKEWORD(2, 2); iResult = WSAStartup(wVersionRequested, &wsaData); if (iResult != 0) { printf("WSAStartup failed with error: %d\n", iResult); return false; } else { printf("WSAStartup succeeded!\n"); return true; } } bool MyTCPSocket::CreateSocket() { m_Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (INVALID_SOCKET == m_Socket) { printf("INVALID_SOCKET\n"); return false; } printf("Create Socket(%d) successully.\n",m_Socket); BOOL reuseaddr=TRUE; setsockopt(m_Socket,SOL_SOCKET,SO_REUSEADDR,(const char*)&reuseaddr,sizeof(reuseaddr)); return true; } bool MyTCPSocket::Bind(unsigned aPost,const char* aAdress) { struct sockaddr_in server_addr; // server address information server_addr.sin_family = AF_INET; // host byte order server_addr.sin_port = htons(aPost); // short, network byte order server_addr.sin_addr.s_addr = inet_addr(aAdress); // automatically fill with my IP memset(server_addr.sin_zero, '\0', sizeof(server_addr.sin_zero)); if (-1 == bind(m_Socket,(struct sockaddr *)&server_addr,sizeof(server_addr))) { printf("Bind Error.\n"); return false; } int nRecvBuf = 32 * 1024; //设置为32K if (setsockopt(m_Socket,SOL_SOCKET,SO_RCVBUF,(const char*)&nRecvBuf,sizeof(int)) == -1) { perror("setsockopt"); exit(1); } return true; } bool MyTCPSocket::Connect( unsigned aPost,const char* aAdress ) { sockaddr_in lsockaddr_in; lsockaddr_in.sin_family = AF_INET; lsockaddr_in.sin_port = htons(aPost); lsockaddr_in.sin_addr.s_addr = inet_addr(aAdress); if (-1 == connect(m_Socket,(struct sockaddr *)&lsockaddr_in,sizeof(lsockaddr_in))) { printf("Conenct Error.\n"); return false; } return true; } bool MyTCPSocket::Listen( int aBacklog/*=5*/ ) { if (-1 == listen(m_Socket,aBacklog)) { printf("Listen Error.\n"); return false; } return true; } bool MyTCPSocket::Send( const char* aBuf) { if (-1 == send(m_Socket,aBuf,strlen(aBuf)+1,0)) { printf("Send Error.\n"); return false; } return true; } bool MyTCPSocket::Recv() { char lBuf[2048]; int lLength = 0; lLength = recv(m_ClientSocket,lBuf,sizeof(lBuf),0); if (SOCKET_ERROR == lLength || 0 == lLength) { closesocket(m_ClientSocket); return false; } int lBegin = 0; int lEnd = 0; for (;lEnd < lLength;++lEnd) { if ('\0' == lBuf[lEnd]) { char lData[1024]; int lLen = lEnd-lBegin; memcpy(lData,lBuf+lBegin,lLen+1); printf("We successfully received %d byte: %s.\n", lLen, lData); lBegin = lEnd+1; } } if (lEnd < lLength) { char lData[1024]; memcpy(lData,lBuf+lBegin,lEnd-lBegin); lData[lEnd] = '\0'; printf("We successfully received %d byte: %s.\n", lData); } return true; } bool MyTCPSocket::UnInit() { if (-1 == closesocket(m_Socket)) { printf("Close Socket Error.\n"); return false; } printf("Close Socket(%d).\n",m_Socket); return true; } void MyTCPSocket::Accept() { int lAddrLen = sizeof(m_SockClientaddrIn); m_ClientSocket = accept(m_Socket, (sockaddr*)&m_SockClientaddrIn,&lAddrLen); printf("We successfully got a connection from %s:%d.\n", inet_ntoa(m_SockClientaddrIn.sin_addr), ntohs(m_SockClientaddrIn.sin_port)); HANDLE handle = ::CreateThread(NULL, 0, WorkerFun,NULL, 0, NULL); } DWORD WINAPI WorkerFun( LPVOID aData ) { printf("Create Worker Thread.\n"); SOCKET lSocket = (SOCKET)(aData); char lBuf[2048]; int lLength = 0; lLength = recv(lSocket,lBuf,sizeof(lBuf),0); if (SOCKET_ERROR == lLength || 0 == lLength) { closesocket(lSocket); return false; } int lBegin = 0; int lEnd = 0; for (;lEnd < lLength;++lEnd) { if ('\0' == lBuf[lEnd]) { char lData[1024]; int lLen = lEnd-lBegin; memcpy(lData,lBuf+lBegin,lLen+1); printf("We successfully received %d byte: %s.\n", lLen, lData); lBegin = lEnd+1; } } if (lEnd < lLength) { char lData[1024]; memcpy(lData,lBuf+lBegin,lEnd-lBegin); lData[lEnd] = '\0'; printf("We successfully received %d byte: %s.\n", lData); } return 0; }
测试代码:
#include <stdio.h> #include "MyTCPSocket.h" void ServerStart() { MyTCPSocket lServer; lServer.Init(); lServer.CreateSocket(); lServer.Bind(1234,"192.168.28.1"); lServer.Listen(); lServer.Accept(); while(1) { if (!lServer.Recv()) { break; } } lServer.UnInit(); } void ClientStart() { MyTCPSocket lServer; lServer.Init(); lServer.CreateSocket(); if (!lServer.Connect(1234,"192.168.28.1")) { lServer.UnInit(); return; } for (int i =0; i <10;++i) { lServer.Send("hell0"); } lServer.UnInit(); } int main() { ServerStart(); }
表示只是刚开始瞎写,很丑 有木有,赶快改进 有木有!
不过经测试,还是不错滴,博客园有大侠封装的更好的木有,写代码不想注释啊,介个可不可以上首页,大侠猛戳呀,哈哈!