那么我们如何让两台局域网的两个计算机实现通信呢?我们需要借助一台公网IP计算机来完成。具有公网IP的计算机充当中间人,两台局域网的计算机都可以向具备公网IP的计算机发起通信。这样的话,中间人就在中间转发双方的数据,这样就实现了内网穿透(内网打洞)。或者,中间人降低参与度,直接将双方的套接字信息共享给双方。比如中间人将连入的所有的计算机的联系方式都公布在公告栏里,这样所有的计算机都可以根据公告栏里的联系方式直接线下连接了。
QQ通信方式是服务器转发数据的方式,这样服务器可以实现数据过滤控制,可以提供更多的服务,比如QQ好友服务。而直接公布联系方式的做法,服务器只是作为查询的工具,参与度很低,很难从中获利。
我们这里介绍的就是QQ的模式,服务器中转数据实现内网穿透。实际上这种模式使用的太多太多了。各种远程控制软件、通信软件等等,都会使用的。
我们使用libuv库来实现这个功能,非常简单,简单到难以置信。
我们使用的主要代码,就用我之前分享的libuv服务端封装类来做。代码见《libuv服务器端包装类源代码分享》。
我们自己提供一个main函数,代码如下:
int main()
{
g_srv.setnewconnectcb(new_conn_cb);
g_srv.Start("0.0.0.0", 6111);
return 0;
}
然后提供回调函数和全局服务端变量的代码如下:CTcpServer g_srv;
void recv_cb(int client_id, const char* buf, int buf_size)
{
//处理接受消息
char* tmp = new char[buf_size*2];
memcpy(tmp, buf, buf_size*2);
if (client_id==1)
{
g_srv.send(2, (const char*)tmp, buf_size);
}
if (client_id==2)
{
g_srv.send(1, (const char*)tmp, buf_size);
}
delete[] tmp;
tmp = 0;
}
void new_conn_cb(int client_id)
{
//设置新连接接收数据回调函数
g_srv.setrecvcb(client_id, recv_cb);
}
我们在recv_cb函数中,根据客户端ID变量client_id来识别不同的客户端,我们这里只是做测试,就固定为1和2,也就是先后连接的两个客户端。然后进行交叉数据转发,即1发给2,2发给1。下面是实现的效果: