首页 > 其他分享 >socket端口数据转发

socket端口数据转发

时间:2023-01-20 23:31:28浏览次数:35  
标签:skServer socket 端口 iRecvSum strLog 转发 ShowMessage pTS addr


---------------------------------------------------------------------------

先说下我的需求:

因工作的需要,别的电脑在访问我的电脑的80端口时,我希望其访问的其实是某台设备的80端口,

因为我的电脑根本没有web服务,提供web服务的其实是某台设备,公司有很多台设备哈。。。

而别的电脑只能访问我的电脑,不能直接访问设备。。。

为了别的电脑能通过我的电脑访问到设备,因此我写了这个程序。。。

------------------------------------------------------------------------------------------------------

该demo程序我测试了百度、人人网、博客园,都可以通过我的程序进行转发访问,

说明我的想法真的可以实现了。。。

为了测试,需要修改以下文件:

C:\Windows\System32\drivers\etc\hosts

如我的为:

192.168.1.3 www.renren.com
192.168.1.3 www.baidu.com
192.168.1.3 www.cnblogs.com

socket端口数据转发_端口转发

-------------------------------------------------------------------------------------

程序效果如下:

socket端口数据转发_hosts_02

-----------------------------------------------------------------------------------------------------------

关键代码如下:


// 80端口监听线程
void CTranspondDlg::ThreadListenPort80( void )
{
ShowMessage("进入ThreadListenPort80");

SOCKET skServer = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (INVALID_SOCKET == skServer)
{
ShowMessage("创建socket失败");
m_bIsStop = true;
}
SOCKADDR_IN skSvrAddr;
skSvrAddr.sin_family = AF_INET;
skSvrAddr.sin_port = htons(80);
skSvrAddr.sin_addr.S_un.S_addr = ADDR_ANY;
if (bind(skServer, (struct sockaddr*)&skSvrAddr, sizeof(skSvrAddr)) == SOCKET_ERROR)
{
ShowMessage("80端口绑定socket失败");
m_bIsStop = true;
}
if (listen(skServer, SOMAXCONN) == SOCKET_ERROR)
{
ShowMessage("80端口监听socket失败");
m_bIsStop = true;
}
else
{
ShowMessage("socket监听80端口成功,等待客户连接...");
}

CString strLog;
while(!m_bIsStop)
{
if (SOCKET_Select(skServer, 500, TRUE))
{
SOCKET skClient;
int iAddrLen = sizeof(SOCKADDR_IN);
SOCKADDR_IN skAddrClient;
skClient = accept(skServer, (sockaddr*)&skAddrClient, &iAddrLen);
strLog.Format("有客户连接:%s:%d", inet_ntoa(skAddrClient.sin_addr), ntohs(skAddrClient.sin_port));
ShowMessage(strLog);

// 连接真正的web服务器
SOCKET skWeb = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (skWeb == skServer)
{
ShowMessage("创建web socket失败");
m_bIsStop = true;
break;
}
SOCKADDR_IN skAddrWeb;
skAddrWeb.sin_family = AF_INET;
skAddrWeb.sin_port = htons(80);
skAddrWeb.sin_addr.S_un.S_addr = inet_addr("180.97.33.108"); // 百度
//skAddrWeb.sin_addr.S_un.S_addr = inet_addr("220.181.181.224"); // 人人
//skAddrWeb.sin_addr.S_un.S_addr = inet_addr("42.121.252.58"); // cnblogs
if (connect(skWeb, (sockaddr*)&skAddrWeb, sizeof(sockaddr)) == SOCKET_ERROR)
{
ShowMessage("连接web服务器失败");
m_bIsStop = true;
break;
}

// 开启数据转发线程
TranspondSocket transpondSocket;
transpondSocket.pThis = this;
transpondSocket.skClient = skClient;
transpondSocket.skServer = skWeb;
HANDLE hTmp = (HANDLE)_beginthreadex(NULL, 0, ThreadTranspondDataProxy, &transpondSocket, 0, NULL);
CloseHandle(hTmp);
hTmp = NULL;
}
}

closesocket(skServer);
ShowMessage("退出ThreadListenPort80");
}


----------------------------------------------------------------

// 数据转发线程
void CTranspondDlg::ThreadTranspondData( LPVOID pvParam )
{
ShowMessage("进入ThreadTranspondData");
CString strLog;
TranspondSocket *pTS = (TranspondSocket*)pvParam;
if (pTS == NULL)
{
ShowMessage("ThreadTranspondData 参数错误");
ShowMessage("退出ThreadTranspondData");
return;
}

// SIO_KEEPALIVE_VALS 机制
//structtcp_keepalive {
// ULONGonoff ; // 是否开启keepalive
// ULONGkeepalivetime ; // 多长时间(ms)没有数据就开始send心跳包
// ULONGkeepaliveinterval ; // 每隔多长时间(ms)send一个心跳包,
// // 发5次(2000 XP 2003默认), 10次(Vista后系统默认)
//};

//tcp_keepalive inKeepAlive = {0};
//tcp_keepalive outKeepAlive = {0};
//unsigned long ulInLen = sizeof(tcp_keepalive);
//unsigned long ulOutLen = sizeof(tcp_keepalive);
//unsigned long ulBytesReturn = 0;
//inKeepAlive.onoff = 1;
//inKeepAlive.keepaliveinterval = 1000; //单位为毫秒
//inKeepAlive.keepalivetime = 1000; //单位为毫秒
//int iRet = WSAIoctl(pTS->skClient, SIO_KEEPALIVE_VALS, (LPVOID)&inKeepAlive, ulInLen, (LPVOID)&outKeepAlive, ulOutLen, &ulBytesReturn, NULL, NULL);
//if (iRet != 0)
//{
// strLog.Format("WSAIoctl错误, ErrCode=%d", WSAGetLastError());
// ShowMessage(strLog);
// ShowMessage("退出ThreadTranspondData");
// return;
//}
//iRet = WSAIoctl(pTS->skClient, SIO_KEEPALIVE_VALS, (LPVOID)&inKeepAlive, ulInLen, (LPVOID)&outKeepAlive, ulOutLen, &ulBytesReturn, NULL, NULL);
//if (iRet != 0)
//{
// strLog.Format("WSAIoctl错误, ErrCode=%d", WSAGetLastError());
// ShowMessage(strLog);
// ShowMessage("退出ThreadTranspondData");
// return;
//}

bool bIsExit = false;
int iRecvSum = 0;
int iSendSum = 0;
char szBuf[4096] = {0};
DWORD dwErroCode = 0;
while(!m_bIsStop)
{
if (bIsExit)
{
break;
}
memset(szBuf, 0, sizeof(szBuf));
iRecvSum = 0;
iSendSum = 0;

// 接收客户端数据
while(SOCKET_Select(pTS->skClient, 100, TRUE))
{
iRecvSum = recv(pTS->skClient, szBuf, sizeof(szBuf), 0);
dwErroCode = WSAGetLastError();

// 判断客户端是否断开
if (WSAGetLastError() == WSAECONNRESET)
{
ShowMessage("客户端断开");
bIsExit = true;
break;
}
if (iRecvSum <= 0)
{
strLog.Format("没有收到服客户端数据:dwErroCode=%d", dwErroCode);
ShowMessage(strLog);
bIsExit = true;
break;
}
strLog.Format("收到客户端数据:iReadSum=%d", iRecvSum);
ShowMessage(strLog);
strLog.Format("%s", szBuf);
ShowMessage(strLog);

// 将客户请求的数据发给真正的服务器
iSendSum = send(pTS->skServer, szBuf, iRecvSum, 0);
strLog.Format("给服务器发送数据:iSendSum=%d, ErrCode=%d", iSendSum, WSAGetLastError());
ShowMessage(strLog);
}

// 接收真正的服务器返回来的数据
while(SOCKET_Select(pTS->skServer, 100, TRUE))
{
iRecvSum = recv(pTS->skServer, szBuf, sizeof(szBuf), 0);
dwErroCode = WSAGetLastError();

// 判断服务器是否断开
if (WSAGetLastError() == WSAECONNRESET)
{
ShowMessage("服务器断开");
bIsExit = true;
break;
}

if (iRecvSum <= 0)
{
strLog.Format("没有收到服务器数据:dwErroCode=%d", dwErroCode);
ShowMessage(strLog);
bIsExit = true;
break;
}
strLog.Format("收到服务器数据:iRecvSum=%d", iRecvSum);
ShowMessage(strLog);
strLog.Format("%s", szBuf);
ShowMessage(strLog);

// 将服务器数据发给客户端
iSendSum = send(pTS->skClient, szBuf, iRecvSum, 0);
strLog.Format("发送给客户端数据:iSendSum=%d, ErrCode=%d", iSendSum, WSAGetLastError());
ShowMessage(strLog);
}
}

closesocket(pTS->skClient);
closesocket(pTS->skServer);
ShowMessage("退出ThreadTranspondData");
}

 

------------------------------------------------------------------------

唯一的缺点就是,客户端掉线的检测机制不是很好,留给需要的人去完善吧。。。


 

 

标签:skServer,socket,端口,iRecvSum,strLog,转发,ShowMessage,pTS,addr
From: https://blog.51cto.com/softo/6020857

相关文章