周五去一个公司打了个酱油,面试官问我:你封装过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();
}
表示只是刚开始瞎写,很丑 有木有,赶快改进 有木有!
不过经测试,还是不错滴,博客园有大侠封装的更好的木有,写代码不想注释啊,介个可不可以上首页,大侠猛戳呀,哈哈!