中介服务器,p2p-s.c:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define SERVER_PORT 12345
int main()
{
int sockfd;
struct sockaddr_in server_addr, client1_addr, client2_addr, *client_addr_in;
char buffer[1024];
char ip_address[INET_ADDRSTRLEN];
int port;
char client_info_str[30] = {0};
// 创建套接字
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0)
{
perror("socket");
return -1;
}
// 设置服务器地址
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(SERVER_PORT);
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
// 绑定服务器地址
if (bind(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0)
{
perror("bind");
return -1;
}
printf("Server is running...\n");
while (1)
{
printf("等待消息...\n");
socklen_t addr_len = sizeof(struct sockaddr_in);
// 接收来自客户端的消息,以获取客户端的公网IP和端口
recvfrom(sockfd, buffer, sizeof(buffer) - 1, 0, (struct sockaddr *)&client1_addr, &addr_len);
recvfrom(sockfd, buffer, sizeof(buffer) - 1, 0, (struct sockaddr *)&client2_addr, &addr_len);
// 分别转发客户端的公网IP和端口给对方
printf("转发客户端的公网IP和端口\n");
client_addr_in = (struct sockaddr_in *)&client1_addr;
inet_ntop(AF_INET, &(client_addr_in->sin_addr), ip_address, INET_ADDRSTRLEN);
port = ntohs(client_addr_in->sin_port);
printf("client1, ip:%s port:%d\n", ip_address, port);
// 转发给客户端2
sprintf(client_info_str, "%s %d", ip_address, port);
if (sendto(sockfd, client_info_str, strlen(client_info_str), 0, (struct sockaddr *)&client2_addr, sizeof(client2_addr)) < 0)
{
perror("sendto");
return -1;
}
client_addr_in = (struct sockaddr_in *)&client2_addr;
inet_ntop(AF_INET, &(client_addr_in->sin_addr), ip_address, INET_ADDRSTRLEN);
port = ntohs(client_addr_in->sin_port);
printf("client2, ip:%s port:%d\n", ip_address, port);
// 转发给客户端1
sprintf(client_info_str, "%s %d", ip_address, port);
if (sendto(sockfd, client_info_str, strlen(client_info_str), 0, (struct sockaddr *)&client1_addr, sizeof(client1_addr)) < 0)
{
perror("sendto");
return -1;
}
}
// 关闭套接字
close(sockfd);
return 0;
}
客户端a,p2p-a.c:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <unistd.h>
#define SERVER_IP "106.55.27.13" // 中介服务器的IP地址
#define SERVER_PORT 12345
int connect_flag = 0;
void *recv_message(void *arg)
{
int sockfd = *(int *)arg;
char buffer[1024];
while (1)
{
memset(buffer, 0, sizeof(buffer));
if (recvfrom(sockfd, buffer, sizeof(buffer) - 1, 0, NULL, NULL) < 0)
{
perror("recvfrom");
return NULL;
}
printf("recv: %s\n", buffer);
connect_flag = 1;
}
}
int main()
{
int sockfd;
struct sockaddr_in server_addr, clientB_addr;
char buffer[1024] = {0};
char clientB_ip[16];
int clientB_port;
pthread_t tid;
// 创建套接字
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0)
{
perror("socket");
return -1;
}
// 设置服务器地址
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(SERVER_PORT);
if (inet_pton(AF_INET, SERVER_IP, &(server_addr.sin_addr)) <= 0)
{
perror("inet_pton");
return -1;
}
// 发送消息给中介服务器
char request[] = "hello";
if (sendto(sockfd, request, strlen(request), 0, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0)
{
perror("sendto");
return -1;
}
// 等待接收客户端B的公网IP和端口
ssize_t recv_len = recvfrom(sockfd, buffer, sizeof(buffer) - 1, 0, NULL, NULL);
if (recv_len >= 0)
{
// 解析中介服务器发送的客户端B的公网IP和端口
sscanf(buffer, "%s %d", clientB_ip, &clientB_port);
printf("clientB, ip:%s port:%d\n", clientB_ip, clientB_port);
memset(&clientB_addr, 0, sizeof(clientB_addr));
clientB_addr.sin_family = AF_INET;
clientB_addr.sin_port = htons(clientB_port);
if (inet_pton(AF_INET, clientB_ip, &(clientB_addr.sin_addr)) <= 0)
{
perror("inet_pton");
return -1;
}
// 启动一个接收信息的线程
pthread_create(&tid, NULL, recv_message, (void *)&sockfd);
// 打洞
while(!connect_flag)
{
sendto(sockfd, "111", strlen("111"), 0, (struct sockaddr *)&clientB_addr, sizeof(clientB_addr));
usleep(1000 * 500);
}
printf("打洞成功\n");
while (1)
{
memset(buffer, 0, sizeof(buffer));
// 发送消息
scanf("%s", buffer);
printf("send: %s\n", buffer);
if (sendto(sockfd, buffer, strlen(buffer), 0, (struct sockaddr *)&clientB_addr, sizeof(clientB_addr)) < 0)
{
perror("sendto");
return -1;
}
}
}
// 关闭套接字
close(sockfd);
pthread_join(tid, NULL);
return 0;
}
客户端b,p2p-b.c:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
#define SERVER_IP "106.55.27.13" // 中介服务器的IP地址
#define SERVER_PORT 12345
int connect_flag = 0;
void *recv_message(void *arg)
{
int sockfd = *(int *)arg;
char buffer[1024];
while (1)
{
memset(buffer, 0, sizeof(buffer));
if (recvfrom(sockfd, buffer, sizeof(buffer) - 1, 0, NULL, NULL) < 0)
{
perror("recvfrom");
return NULL;
}
printf("recv: %s\n", buffer);
connect_flag = 1;
}
}
int main()
{
int sockfd;
struct sockaddr_in server_addr, clientA_addr;
char buffer[1024] = {0};
char clientA_ip[16];
int clientA_port;
pthread_t tid;
// 创建套接字
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0)
{
perror("socket");
return -1;
}
// 设置服务器地址
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(SERVER_PORT);
if (inet_pton(AF_INET, SERVER_IP, &(server_addr.sin_addr)) <= 0)
{
perror("inet_pton");
return -1;
}
// 发送消息给中介服务器
char request[] = "hello";
if (sendto(sockfd, request, strlen(request), 0, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0)
{
perror("sendto");
return -1;
}
// 等待接收客户端A的公网IP和端口
ssize_t recv_len = recvfrom(sockfd, buffer, sizeof(buffer) - 1, 0, NULL, NULL);
if (recv_len >= 0)
{
// 解析中介服务器发送的客户端A的公网IP和端口
sscanf(buffer, "%s %d", clientA_ip, &clientA_port);
printf("clientA, ip:%s port:%d\n", clientA_ip, clientA_port);
memset(&clientA_addr, 0, sizeof(clientA_addr));
clientA_addr.sin_family = AF_INET;
clientA_addr.sin_port = htons(clientA_port);
if (inet_pton(AF_INET, clientA_ip, &(clientA_addr.sin_addr)) <= 0)
{
perror("inet_pton");
return -1;
}
// 启动一个接收信息的线程
pthread_create(&tid, NULL, recv_message, (void *)&sockfd);
// 打洞
while (!connect_flag)
{
sendto(sockfd, "222", strlen("222"), 0, (struct sockaddr *)&clientA_addr, sizeof(clientA_addr));
usleep(1000 * 500);
}
printf("打洞成功\n");
while (1)
{
memset(buffer, 0, sizeof(buffer));
// 发送消息
scanf("%s", buffer);
printf("send: %s\n", buffer);
if (sendto(sockfd, buffer, strlen(buffer), 0, (struct sockaddr *)&clientA_addr, sizeof(clientA_addr)) < 0)
{
perror("sendto");
return -1;
}
}
}
// 关闭套接字
close(sockfd);
pthread_join(tid, NULL);
return 0;
}