我是靠谱客的博主 稳重纸鹤,这篇文章主要介绍socket端口数据转发,现在分享给大家,希望可以做个参考。

参考文章:http://blog.csdn.net/wangyi_lin/article/details/9277717?utm_source=tuicool

 灵感来源于lcx.exe

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

先说下我的需求:

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

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

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

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

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

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

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

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

C:WindowsSystem32driversetchosts

如我的为:

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


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

程序效果如下:


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

关键代码如下:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
// 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"); }

----------------------------------------------------------------
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
// 数据转发线程 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"); }


 

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

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

程序VS2010源码工程下载:

 http://download.csdn.net/detail/friendan/8684207

 

 

 

最后

以上就是稳重纸鹤最近收集整理的关于socket端口数据转发的全部内容,更多相关socket端口数据转发内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(82)

评论列表共有 0 条评论

立即
投稿
返回
顶部