int nTimes = 0;
int DataSend(SOCKET s, char *DataBuf, int DataLen)//将DataBuf中的DataLen个字节发到s去
{
int nBytesLeft = DataLen;
int nBytesSent = 0;
int ret;
//set socket to blocking mode
int iMode = 0;
ioctlsocket(s, FIONBIO, (u_long FAR*) &iMode);
while(nBytesLeft > 0)
{
ret = send(s, DataBuf + nBytesSent, nBytesLeft, 0);
if(ret <= 0)
break;
nBytesSent += ret;
nBytesLeft -= ret;
}
return nBytesSent;
}
DWORD WINAPI TransmitData(LPVOID lParam)//在两个SOCKET中进行数据转发
{
SOCKINFO socks = *((SOCKINFO*)lParam);
SOCKET ClientSock = socks.ClientSock;
SOCKET ServerSock = socks.ServerSock;
char RecvBuf[MAXBUFSIZE] = {0};
fd_set Fd_Read;
int ret, nRecv;
while(1)
{
FD_ZERO(&Fd_Read);
FD_SET(ClientSock, &Fd_Read);
FD_SET(ServerSock, &Fd_Read);
ret = select(0, &Fd_Read, NULL, NULL, NULL);
if(ret <= 0)
goto error;
if(FD_ISSET(ClientSock, &Fd_Read))
{
nRecv = recv(ClientSock, RecvBuf, sizeof(RecvBuf), 0);
if(nRecv <= 0)
goto error;
ret = DataSend(ServerSock, RecvBuf, nRecv);
if(ret == 0 || ret != nRecv)
goto error;
}
if(FD_ISSET(ServerSock, &Fd_Read))
{
nRecv = recv(ServerSock, RecvBuf, sizeof(RecvBuf), 0);
if(nRecv <= 0)
goto error;
ret = DataSend(ClientSock, RecvBuf, nRecv);
if(ret == 0 || ret != nRecv)
goto error;
}
}
error:
closesocket(ClientSock);
closesocket(ServerSock);
return 0;
}
SOCKET ConnectHost(DWORD dwIP, WORD wPort)//连接指定IP和端口
{
SOCKET sockid;
if ((sockid = socket(AF_INET,SOCK_STREAM,0)) == INVALID_SOCKET)
return 0;
struct sockaddr_in srv_addr;
srv_addr.sin_family = AF_INET;
srv_addr.sin_addr.S_un.S_addr = dwIP;
srv_addr.sin_port = htons(wPort);
if (connect(sockid,(struct sockaddr*)&srv_addr,sizeof(struct sockaddr_in)) == SOCKET_ERROR)
goto error;
return sockid;
error:
closesocket(sockid);
return 0;
}
SOCKET ConnectHost(char *szIP, WORD wPort)
{
return ConnectHost(inet_addr(szIP), wPort);
}
SOCKET CreateSocket(DWORD dwIP, WORD wPort)//在dwIP上绑定wPort端口
{
SOCKET sockid;
if ((sockid = socket(AF_INET,SOCK_STREAM,0)) == INVALID_SOCKET)
return 0;
struct sockaddr_in srv_addr = {0};
srv_addr.sin_family = AF_INET;
srv_addr.sin_addr.S_un.S_addr = dwIP;
srv_addr.sin_port = htons(wPort);
if (bind(sockid,(struct sockaddr*)&srv_addr,sizeof(struct sockaddr_in)) == SOCKET_ERROR)
goto error;
listen(sockid,3);
return sockid;
error:
closesocket(sockid);
return 0;
}
SOCKET CreateTmpSocket(WORD *wPort)//创建一个临时的套接字,指针wPort获得创建的临时端口
{
struct sockaddr_in srv_addr = {0};
int addrlen = sizeof(struct sockaddr_in);
SOCKET s = CreateSocket(INADDR_ANY, 0);
if(s <= 0)
goto error;
if(getsockname(s, (struct sockaddr*)&srv_addr, &addrlen) == SOCKET_ERROR)
goto error;
*wPort = ntohs(srv_addr.sin_port);
return s;
error:
closesocket(s);
return 0;
}
BOOL InitSocket()
{
WSADATA wsadata;
return WSAStartup(MAKEWORD(2,2),&wsadata) == 0;
}
DWORD WINAPI PortTransfer_1(LPVOID lParam)
{
TransferParam<ADDRESS, SOCKET> *ConfigInfo = (TransferParam<ADDRESS, SOCKET>*)lParam;
SOCKET ClientSock, ServerSock;
//出栈,获得客户的套接字
ClientSock = ConfigInfo->LocalData.Pop();
printf("ThreadID: %d ==> Now Connecting To Server...", nTimes);
//先连接到目标计算机的服务
ServerSock = ConnectHost(ConfigInfo->GlobalData.szIP, ConfigInfo->GlobalData.wPort);
if(ServerSock <= 0)
{
printf("Error.\r\n");
closesocket(ClientSock);
return 0;
}
printf("OK.\r\nStarting TransmitData\r\n");
SOCKINFO socks;
socks.ClientSock = ClientSock;//客户的套接字
socks.ServerSock = ServerSock;//目标计算机服务的套接字
//进入纯数据转发状态
return TransmitData((LPVOID)&socks);
}
BOOL PortTransfer_1(WORD ListenPort, char *szIP, WORD wPort)
{
HANDLE hThread;
DWORD dwThreadId;
SOCKET AcceptSocket;
TransferParam<ADDRESS, SOCKET> ConfigInfo;
_snprintf(ConfigInfo.GlobalData.szIP, ADDRSIZE, "%s", szIP);
ConfigInfo.GlobalData.wPort = wPort;
//
监听个服务端口,即映射端口
SOCKET localsockid = CreateSocket(INADDR_ANY, ListenPort);
if(localsockid <= 0)
goto error;
while(1)
{
printf("Accepting new Client...");
AcceptSocket = accept(localsockid, NULL, NULL);
if(AcceptSocket == INVALID_SOCKET)
goto error;
nTimes++;
printf("OK.\r\n");
//将接受到的客户请求套接字转到新的线程里处理
//然后继续等待新的请求
ConfigInfo.LocalData.Push(AcceptSocket);
hThread = CreateThread(NULL, 0, PortTransfer_1, (LPVOID)&ConfigInfo, NULL, &dwThreadId);
if(hThread)
CloseHandle(hThread);
else
Sleep(1000);
}
error:
printf("Error.\r\n");
closesocket(localsockid);
return false;
}
DWORD WINAPI PortTransfer_2(LPVOID lParam)
{
TransferParam<ADDRESS, WORD> *ConfigInfo = (TransferParam<ADDRESS, WORD> *)lParam;
SOCKET CtrlSocket = ConfigInfo->GlobalData.s;
DWORD dwCtrlIP;
//WORD wPort;
SOCKADDR_IN clientaddr;
int addrlen = sizeof(clientaddr);
//之前用错了个API(getsockname),这里应该用getpeername
if(getpeername(CtrlSocket, (SOCKADDR *)&clientaddr, &addrlen) == SOCKET_ERROR)
return 0;
//获得运行PortTransfer_3模式的计算机的IP
dwCtrlIP = clientaddr.sin_addr.S_un.S_addr;
//wPort = ntohs(clientaddr.sin_port);
SOCKET ClientSocket, ServerSocket;
SOCKINFO socks;
printf("ThreadID: %d ==> Connecting to Client...", nTimes);
//向公网建立新的连接
ClientSocket = ConnectHost(dwCtrlIP, ConfigInfo->LocalData.Pop());
if(ClientSocket <= 0)
return 0;
printf("OK.\r\n");
printf("ThreadID: %d ==> Connect to Server...", nTimes);
//连接到目标计算机的服务
ServerSocket = ConnectHost(ConfigInfo->GlobalData.szIP, ConfigInfo->GlobalData.wPort);
if(ServerSocket <= 0)
{
printf("Error.\r\n");
closesocket(ClientSocket);
return 0;
}
printf("OK.\r\nStarting TransmitData\r\n", nTimes);
socks.ClientSock = ClientSocket;//公网计算机的套接字
socks.ServerSock = ServerSocket;//目标计算机服务的套接字
//进入纯数据转发状态
return TransmitData((LPVOID)&socks);
}
BOOL PortTransfer_2(char *szCtrlIP, WORD wCtrlPort, char *szIP, WORD wPort)
{
int nRecv;
WORD ReqPort;
HANDLE hThread;
DWORD dwThreadId;
TransferParam<ADDRESS, WORD> ConfigInfo;
_snprintf(ConfigInfo.GlobalData.szIP, ADDRSIZE, "%s", szIP);
ConfigInfo.GlobalData.wPort = wPort;
printf("Creating a ctrlconnection...");
//与PortTransfer_3模式(工作在共网)的计算机建立控制管道连接
SOCKET CtrlSocket = ConnectHost(szCtrlIP, wCtrlPort);
if(CtrlSocket <= 0)
goto error;
ConfigInfo.GlobalData.s = CtrlSocket;
printf("OK.\r\n");
while(1)
{
//接收来自(工作在公网)计算机的命令,数据为一个WORD,