4,356
社区成员
发帖
与我相关
我的任务
分享
#include <stdio.h>
#include <winsock2.h>
#pragma comment (lib, "ws2_32.lib")
#define BUF_SIZE 100
int main() {
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);
//创建套接字
SOCKET servSock = socket(AF_INET, SOCK_DGRAM, 0);
//绑定套接字
sockaddr_in sockAddr;//本机服务器地址
memset(&sockAddr, 0, sizeof(sockAddr)); //每个字节都用0填充
sockAddr.sin_family = PF_INET; //使用IPv4地址
sockAddr.sin_addr.s_addr = htonl(INADDR_ANY); //自动获取自己的ip地址
sockAddr.sin_port = htons(10086); //监听服务端口
bind(servSock, (SOCKADDR*)&sockAddr, sizeof(SOCKADDR));//绑定端口
//接收客户端请求
sockaddr_in clntAddr1; //客户端1地址信息
int nSize = sizeof(SOCKADDR);
char RecvBuffer[BUF_SIZE]; //缓冲区
int strLen = recvfrom(servSock, RecvBuffer, BUF_SIZE, 0, (struct sockaddr*)&clntAddr1, &nSize);
sockaddr_in clntAddr2; //客户端2地址信息
strLen = recvfrom(servSock, RecvBuffer, BUF_SIZE, 0, (struct sockaddr*)&clntAddr2, &nSize);
//把两边的地址准备好发送
char bufSend1[BUF_SIZE];
memset(bufSend1, '\0', sizeof(bufSend1));
char* ip1 = inet_ntoa(clntAddr2.sin_addr);
char port1[10];
_itoa_s(ntohs(clntAddr2.sin_port), port1, 10);
for (int i = 0; i<strlen(ip1); i++) {
bufSend1[i] = ip1[i];
}
bufSend1[strlen(ip1)] = '^';
for (int i = 0; i<strlen(port1); i++) {
bufSend1[strlen(ip1) + 1 + i] = port1[i];
}
char bufSend2[BUF_SIZE];
memset(bufSend2, '\0', sizeof(bufSend2));
char* ip2 = inet_ntoa(clntAddr1.sin_addr);
char port2[10];
_itoa_s(ntohs(clntAddr1.sin_port), port2, 10);
for (int i = 0; i<strlen(ip2); i++) {
bufSend2[i] = ip2[i];
}
bufSend2[strlen(ip2)] = '^';
for (int i = 0; i<strlen(port2); i++) {
bufSend2[strlen(ip2) + 1 + i] = port2[i];
}
//发送 交换地址
strLen = sendto(servSock, bufSend1, sizeof(bufSend1), 0, (struct sockaddr*)&clntAddr1, sizeof(clntAddr1));
strLen = sendto(servSock, bufSend2, sizeof(bufSend2), 0, (struct sockaddr*)&clntAddr2, sizeof(clntAddr2));
printf("发送目标1:ip:%s 端口号:%d\n", inet_ntoa(clntAddr1.sin_addr),ntohs(clntAddr1.sin_port));
printf("发送内容1:%s\n", bufSend1);
printf("发送目标2:ip:%s 端口号:%d\n", inet_ntoa(clntAddr2.sin_addr), ntohs(clntAddr2.sin_port));
printf("发送内容2:%s\n", bufSend2);
printf("交换工作已完成\n");
//停在这里等c1通知s来通知c2
sockaddr_in clntAddr3;
strLen = recvfrom(servSock, RecvBuffer, BUF_SIZE, 0, (struct sockaddr*)&clntAddr3, &nSize);
printf("已收到通知\n");
printf("C1现在的地址是:%s ;%d\n", inet_ntoa(clntAddr3.sin_addr), ntohs(clntAddr3.sin_port));
//区分clntAddr1和clntAddr2,发送给c2通知
if (strcmp(inet_ntoa(clntAddr3.sin_addr), inet_ntoa(clntAddr1.sin_addr)) == 0&& ntohs(clntAddr3.sin_port)== ntohs(clntAddr1.sin_port))
{
strLen = sendto(servSock, bufSend2, sizeof(bufSend2), 0, (struct sockaddr*)&clntAddr2, sizeof(clntAddr2));
printf("发送目标3:ip:%s 端口号:%d\n", inet_ntoa(clntAddr2.sin_addr), ntohs(clntAddr2.sin_port));
}
else
{
strLen = sendto(servSock, bufSend1, sizeof(bufSend1), 0, (struct sockaddr*)&clntAddr1, sizeof(clntAddr1));
printf("发送目标4:ip:%s 端口号:%d\n", inet_ntoa(clntAddr1.sin_addr), ntohs(clntAddr1.sin_port));
}
system("pause()");
closesocket(servSock);
WSACleanup();
return 0;
}
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.*;
import java.sql.Time;
/**
* Created by lgtczh on 2017/7/21.
*/
public class TCPclientA {
public static void main(String[] args) throws IOException {
try {
// 向server发起请求
SocketAddress target1 = new InetSocketAddress("114.55.101.163", 10086);
DatagramSocket client = new DatagramSocket(10086);
String message = "";
byte[] sendbuf = message.getBytes();
DatagramPacket pack = new DatagramPacket(sendbuf, sendbuf.length, target1);
client.send(pack);
// 接收服务器返回的C2地址
byte[] buf = new byte[1024];
DatagramPacket recvPacket = new DatagramPacket(buf, buf.length);
client.receive(recvPacket);//会停在这里
String receiveMessage = new String(recvPacket.getData(), 0, recvPacket.getLength());
//解析B的IP和端口号
String[] params = receiveMessage.split("\\^");
String host = params[0].substring(0);
String port = params[1].substring(0);
System.out.println(host+" "+port);
SocketAddress target2 = new InetSocketAddress(host, Integer.parseInt(port.trim()));
DatagramPacket pack2 = new DatagramPacket(sendbuf, sendbuf.length, target2);
//向C2打洞
client.send(pack2);
System.out.println("已打洞");
//通知服务器通知C2已打洞
client.send(pack);
//等待接收C2发送过来
buf=new byte[1024];
recvPacket = new DatagramPacket(buf, buf.length);
client.receive(recvPacket);//会停在这里
client.send(pack2);//向C2发送过去,若发到则已打通
receiveMessage = new String(recvPacket.getData(), 0, recvPacket.getLength());
System.out.println("已成功打通 "+receiveMessage);
} catch (Exception e) {
e.printStackTrace();
}
}
}
#include <stdio.h>
#include <WinSock2.h>
#pragma comment(lib, "ws2_32.lib")
#define BUF_SIZE 100
int main() {
//初始化DLL
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);
//创建套接字
SOCKET sock = socket(PF_INET, SOCK_DGRAM, 0);
//服务器地址信息
sockaddr_in servAddr;
memset(&servAddr, 0, sizeof(servAddr)); //每个字节都用0填充
servAddr.sin_family = PF_INET;
servAddr.sin_addr.s_addr = inet_addr("114.55.101.163");
servAddr.sin_port = htons(10086);
//发送给服务器自己地址
sockaddr fromAddr;
int addrLen = sizeof(fromAddr);
char SendBuffer[BUF_SIZE] = { 0 };
sendto(sock, SendBuffer, strlen(SendBuffer), 0, (struct sockaddr*)&servAddr, sizeof(servAddr));
//接收服务器传来的对面的地址
char RecvBuffer[BUF_SIZE] = { 0 };
int strLen = recvfrom(sock, RecvBuffer, BUF_SIZE, 0, &fromAddr, &addrLen);
//解析对面的地址
char ip[20];
char port[10];
int i;
for (i = 0; i<strlen(RecvBuffer); i++)
if (RecvBuffer[i] != '^')
ip[i] = RecvBuffer[i];
else break;
ip[i] = '\0';
int j;
for (j = i + 1; j<strlen(RecvBuffer); j++)
port[j - i - 1] = RecvBuffer[j];
port[j - i - 1] = '\0';
printf("收到的地址为: %s ,%s\n", ip, port);
//收到通知,给C1发送消息
sockaddr_in opposite;
opposite.sin_family = PF_INET;
opposite.sin_addr.s_addr = inet_addr(ip);
opposite.sin_port = htons(atoi(port));
memset(SendBuffer, 0, BUF_SIZE);
strcpy(SendBuffer,"i am c2");
strLen = sendto(sock, SendBuffer, strlen(SendBuffer), 0, (struct sockaddr*)&opposite, sizeof(opposite));
printf("opposite:%s ;%d\n", inet_ntoa(opposite.sin_addr), ntohs(opposite.sin_port));
printf("%d\n", strLen);
//停下等待服务器通知
strLen = recvfrom(sock, RecvBuffer, BUF_SIZE, 0, &fromAddr, &addrLen);
printf("收到通知\n");
//给C1发信息
strLen = sendto(sock, SendBuffer, strlen(SendBuffer), 0, (struct sockaddr*)&opposite, sizeof(opposite));
printf("%d\n", strLen);
//等待C1返回,若返回则成功
printf("等待C1返回\n");
strLen = recvfrom(sock, RecvBuffer, BUF_SIZE, 0, &fromAddr, &addrLen);
printf("打洞成功\n");
system("pause()");
closesocket(sock);
WSACleanup();
return 0;
}