周五去一个公司打了个酱油,面试官问我:你封装过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=);
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(, );
iResult = WSAStartup(wVersionRequested, &wsaData);
if (iResult != )
{
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 (- == bind(m_Socket,(struct sockaddr *)&server_addr,sizeof(server_addr)))
{
printf("Bind Error.\n");
return false;
} int nRecvBuf = * ; //设置为32K
if (setsockopt(m_Socket,SOL_SOCKET,SO_RCVBUF,(const char*)&nRecvBuf,sizeof(int)) == -) {
perror("setsockopt");
exit();
}
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 (- == 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 (- == listen(m_Socket,aBacklog))
{
printf("Listen Error.\n");
return false;
}
return true;
} bool MyTCPSocket::Send( const char* aBuf)
{
if (- == send(m_Socket,aBuf,strlen(aBuf)+,))
{
printf("Send Error.\n");
return false;
}
return true;
} bool MyTCPSocket::Recv()
{
char lBuf[];
int lLength = ;
lLength = recv(m_ClientSocket,lBuf,sizeof(lBuf),);
if (SOCKET_ERROR == lLength || == lLength)
{
closesocket(m_ClientSocket);
return false;
}
int lBegin = ;
int lEnd = ;
for (;lEnd < lLength;++lEnd)
{
if ('\0' == lBuf[lEnd])
{
char lData[];
int lLen = lEnd-lBegin;
memcpy(lData,lBuf+lBegin,lLen+);
printf("We successfully received %d byte: %s.\n", lLen, lData);
lBegin = lEnd+;
}
}
if (lEnd < lLength)
{
char lData[];
memcpy(lData,lBuf+lBegin,lEnd-lBegin);
lData[lEnd] = '\0';
printf("We successfully received %d byte: %s.\n", lData);
}
return true;
} bool MyTCPSocket::UnInit()
{
if (- == 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, , WorkerFun,NULL, , NULL);
} DWORD WINAPI WorkerFun( LPVOID aData )
{
printf("Create Worker Thread.\n"); SOCKET lSocket = (SOCKET)(aData); char lBuf[];
int lLength = ;
lLength = recv(lSocket,lBuf,sizeof(lBuf),);
if (SOCKET_ERROR == lLength || == lLength)
{
closesocket(lSocket);
return false;
}
int lBegin = ;
int lEnd = ;
for (;lEnd < lLength;++lEnd)
{
if ('\0' == lBuf[lEnd])
{
char lData[];
int lLen = lEnd-lBegin;
memcpy(lData,lBuf+lBegin,lLen+);
printf("We successfully received %d byte: %s.\n", lLen, lData);
lBegin = lEnd+;
}
}
if (lEnd < lLength)
{
char lData[];
memcpy(lData,lBuf+lBegin,lEnd-lBegin);
lData[lEnd] = '\0';
printf("We successfully received %d byte: %s.\n", lData);
}
return ;
}

测试代码:

#include <stdio.h>

#include "MyTCPSocket.h"

void ServerStart()
{
MyTCPSocket lServer;
lServer.Init();
lServer.CreateSocket();
lServer.Bind(,"192.168.28.1");
lServer.Listen();
lServer.Accept(); while()
{
if (!lServer.Recv())
{
break;
}
}
lServer.UnInit();
} void ClientStart()
{
MyTCPSocket lServer;
lServer.Init();
lServer.CreateSocket();
if (!lServer.Connect(,"192.168.28.1"))
{
lServer.UnInit();
return;
}
for (int i =; i <;++i)
{
lServer.Send("hell0");
}
lServer.UnInit();
}
int main()
{
ServerStart();
}

表示只是刚开始瞎写,很丑 有木有,赶快改进 有木有!

不过经测试,还是不错滴,博客园有大侠封装的更好的木有,写代码不想注释啊,介个可不可以上首页,大侠猛戳呀,哈哈!

封装naive socket的更多相关文章

  1. 自己封装的Socket组件,实现服务端多进程共享Socket对象,协同处理客户端请求

    DotNet.Net.MySocket是SLB.NET(Server Load Balance服务器负载均衡)项目中的核心组件. 在实际的项目中发现,单进程的服务端处理高并发的客户请求能力有限. 所以 ...

  2. libevent将信号封装为socket通知的核心代码

    #include"stdafx.h" #include"iostream" #include "algorithm" #include&qu ...

  3. 嵌入式开发之qt socket--- qt 封装的socket demo

    http://wuyuans.com/2013/03/qt-socket/ http://blog.chinaunix.net/uid-22480862-id-388253.html

  4. 封装好的socket,拿去用

    年终有空咯,分享一下自己封装的socket类库. 由于公司写的socket代码非常醉人,我不能忍,所以自己封装了一下方便大家使用,现在有空也分享给园友用用看,现在还存在一定的问题,等下我列出来,希望大 ...

  5. 门面模式的典型应用 Socket 和 Http(post,get)、TCP/IP 协议的关系总结

    门面模式的一个典型应用:Socket 套接字(Socket)是通信的基石,是支持TCP/IP协议的网络通信的基本操作单元.它是网络通信过程中端点的抽象表示,包含进行网络通信必须的五种信息: 连接使用的 ...

  6. java netty socket库和自定义C#socket库利用protobuf进行通信完整实例

    之前的文章讲述了socket通信的一些基本知识,已经本人自定义的C#版本的socket.和java netty 库的二次封装,但是没有真正的发表测试用例. 本文只是为了讲解利用protobuf 进行C ...

  7. Socket初识

    基础概念 Socket,套接字,本质是网络编程接口.提供网络通信的能力,实现不同虚拟机或不同计算机之间的通信.面向客户/服务(C/S)模型,socket是应用层和传输层之间的中间软件抽象层: 顶上三层 ...

  8. TCPIP、Http、Socket的协议~ 写得挺形象,赞

    这篇文章写得挺形象,对TCPIP.HTTP.Socket的作用有一个整体层次的理解. 转载文章内容如下: 网络由下往上分为物理层.数据链路层.网络层.传输层.会话层.表示层和应用层.   通过初步的了 ...

  9. socket.io简单入门(一.实现简单的图表推送)

    引子:随着nodejs蓬勃发展,虽然主要业务系统因为架构健壮性不会选择nodejs座位应用服务器.但是大量的内部系统却可以使用nodejs试水,大量的前端开发人员转入全堆开发也是一个因素. 研究本例主 ...

随机推荐

  1. SendMessage消息大全及说明

    WM_CREATE   =   &H0001     应用程序创建一个窗口     WM_DESTROY   =   &H0002     一个窗口被销毁     WM_MOVE   ...

  2. \r\n 如何转换成utf-8格式的,在jsp页面中正常显示换行

    数据库中存的换行是\r\n,读取到UTF-8编码的JSP 页面上以后,没有换行 在jsp页面显示之前,要进行一下字符转换,将所有\r\n转换成<br>,如下: String result  ...

  3. cmd怎么删除Oracle数据库中的用户实例

    Oracle数据库使用过程中,针对系统都会建立独立的数据库用户,但有些时候处于测试或别的原因需要删除,原来的DB用户,这时我们可以使用下面的办法. 下属操作的前提是——确保数据库服务及监听均处于启动状 ...

  4. Qt学习之路(28): 坐标变换

    经过前面的章节,我们已经能够画出一些东西来,主要就是使用QPainter的相关函数.今天,我们要看的是QPainter的坐标系统.   同很多坐标系统一样,QPainter的默认坐标的原点(0, 0) ...

  5. Android -- isInEditMode

    解释 Indicates whether this View is currently in edit mode. A View is usually in edit mode when displa ...

  6. 4.3 使用 SQL 语句操作数据框

    下载并安装 “sqldf” 包 library(sqldf) newData <- sqldf("select * from mtcars where carb=1 order by ...

  7. OSError: Could not find library geos_c or load any of its variants ['libgeos_c.so.1', 'libgeos_c.so

    OSError: Could not find library geos_c or load any of its variants ['libgeos_c.so.1', 'libgeos_c.so ...

  8. Android 多语言支持

    本文内容 字符串本地化原理 环境 创建项目 测试其他语言 Android 本地化语言 ISO 编码 参考资料 使用 Android 的人越来越多,每天都在增加.因此,当你想把你的应用成功地全球化时,通 ...

  9. WinForm程序开发

    WinForm程序开发------------------------------主要页面----------------------------------BaseForm.cs    基类,用于派 ...

  10. 推荐五星级C语言学习网站

    www.cprogrammingexpert.com (此网站,配合了大量动画,每一行代码,配合一副图片) 下面截取了部分的gif动画,大家可以认真看看, 相信作者花了很多心血,去制作这些动画. sc ...