关于C语言实现去中心化的网络设计 — P2P的代码实现

 

 

 

 

 

 

 

 

 

 

 

那我们如何来进行检测呢,如图所示

 

 

 

 

如何穿透

 

 

 

 

 

 

 

 

见证奇迹的时候到了。先实现个,整个代码逻辑和实现都是按原理方式实现

udp.h

 

​​



#ifndef __UDP_H__
#define __UDP_H__


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>

#include <time.h>

typedef unsigned int U32;
typedef unsigned short U16;
typedef unsigned char U8;
typedef volatile long UATOMIC;
typedef void* (*KING_CALLBACK)(void *arg);

typedef enum {
	KING_RESULT_FAILED = -1,
	KING_RESULT_SUCCESS = 0,
} KING_RESULT;

typedef enum {
	KING_STATUS_NULL,
	KING_STATUS_LOGIN,
	KING_STATUS_HEARTBEAT,
	KING_STATUS_CONNECT,
	KING_STATUS_MESSAGE,
	KING_STATUS_NOTIFY,
	KING_STATUS_P2P_CONNECT,
	KING_STATUS_P2P_MESSAGE,
} KING_STATUS_SET;

#define KING_CLIENT_MAX				1024
#define KING_CLIENT_ADDR_LENGTH		6


#define KING_BUFFER_LENGTH		512

#define KING_NUMBER_ID_LENGTH			4

typedef struct _CLIENT_TABLE {
	U8 addr[KING_CLIENT_ADDR_LENGTH]; 
	U32 client_id;
	long stamp;
} client_table;



/**************************** status define ****************************/


#define KING_PROTO_LOGIN_REQ				0x01
#define KING_PROTO_LOGIN_ACK				0x81


#define KING_PROTO_HEARTBEAT_REQ			0x02
#define KING_PROTO_HEARTBEAT_ACK			0x82


#define KING_PROTO_CONNECT_REQ				0x11
#define KING_PROTO_CONNECT_ACK				0x91

#define NTY_PROTO_NOTIFY_REQ				0x12
#define NTY_PROTO_NOTIFY_ACK				0x92

#define NTY_PROTO_P2P_CONNECT_REQ			0x13
#define NTY_PROTO_P2P_CONNECT_ACK			0x93

#define NTY_RPORO_MESSAGE_REQ				0x21
#define NTY_RPORO_MESSAGE_ACK				0xA1


/**************************** context define ****************************/

#define KING_PROTO_BUFFER_VERSION_IDX		0
#define KING_PROTO_BUFFER_STATUS_IDX		1

#define KING_PROTO_BUFFER_LENGTH_IDX		(KING_PROTO_BUFFER_STATUS_IDX+1)
#define KING_PROTO_BUFFER_SELFID_IDX		(KING_PROTO_BUFFER_LENGTH_IDX+2)

//login
#define KING_PROTO_LOGIN_SELFID_IDX			KING_PROTO_BUFFER_SELFID_IDX 

//heartbeat
#define KING_PROTO_HEARTBEAT_SELFID_IDX		KING_PROTO_BUFFER_SELFID_IDX

//connect
#define KING_PROTO_CONNECT_SELFID_IDX		KING_PROTO_BUFFER_SELFID_IDX
#define KING_PROTO_CONNECT_OTHERID_IDX		(KING_PROTO_BUFFER_SELFID_IDX+KING_NUMBER_ID_LENGTH)

//notify
#define KING_PROTO_NOTIFY_SELFID_IDX			KING_PROTO_BUFFER_SELFID_IDX
#define KING_PROTO_NOTIFY_ADDR_IDX			(KING_PROTO_BUFFER_SELFID_IDX+KING_NUMBER_ID_LENGTH)

//p2p connect
#define KING_PROTO_P2P_CONNECT_SELFID_IDX	KING_PROTO_BUFFER_SELFID_IDX

//p2p connect ack
#define KING_PROTO_P2P_CONNECT_ACK_SELFID_IDX	KING_PROTO_BUFFER_SELFID_IDX


//message
#define KING_RPORO_MESSAGE_SELFID_IDX		KING_PROTO_BUFFER_SELFID_IDX
#define KING_PROTO_MESSAGE_OTHERID_IDX		(KING_RPORO_MESSAGE_SELFID_IDX+KING_NUMBER_ID_LENGTH)
#define KING_RPORO_MESSAGE_CONTENT_IDX		(KING_PROTO_MESSAGE_OTHERID_IDX+KING_NUMBER_ID_LENGTH)

//message ack
#define KING_RPORO_MESSAGE_ACK_SELFID_IDX	KING_PROTO_BUFFER_SELFID_IDX




static unsigned long cmpxchg(UATOMIC *addr, unsigned long _old, unsigned long _new) {
	U8 res;

	__asm__ volatile (
        "lock; cmpxchg %3, %1;sete %0;"
        : "=a" (res)
        : "m" (*addr), "a" (_old), "r" (_new)
        : "cc", "memory");

	return res;
}



static long time_genrator(void) {
	static long lTimeStamp = 0;
	static long timeStampMutex = 0;

	if(cmpxchg(&timeStampMutex, 0, 1)) {
		lTimeStamp = time(NULL);
		timeStampMutex = 0;
	}

	return lTimeStamp;
}



static int addr_to_array(U8 *array, struct sockaddr_in *p_addr) {
	int i = 0;

	for (i = 0;i < 4;i ++) {
		array[i] = *((unsigned char*)(&p_addr->sin_addr.s_addr) + i);
	}

	for (i = 0;i < 2;i ++) {
		array[4+i] = *((unsigned char*)(&p_addr->sin_port)+i);
	}
}

static int array_to_addr(U8 *array, struct sockaddr_in *p_addr) {
	int i = 0;
	
	for (i = 0;i < 4;i ++) {
		*((unsigned char*)(&p_addr->sin_addr.s_addr) + i) = array[i];
	}
	for (i = 0;i < 2;i ++) {
		*((unsigned char*)(&p_addr->sin_port)+i) = array[4+i];
	}
}





static int king_send_login(int sockfd, int self_id, struct sockaddr_in *paddr) {

	U8 buffer[KING_BUFFER_LENGTH] = {0};

	buffer[KING_PROTO_BUFFER_STATUS_IDX] = KING_PROTO_LOGIN_REQ;
	*(int *)(buffer+KING_PROTO_LOGIN_SELFID_IDX) = self_id;

	int n = KING_PROTO_LOGIN_SELFID_IDX + KING_NUMBER_ID_LENGTH;
	n = sendto(sockfd, buffer, n, 0, (struct sockaddr*)paddr, sizeof(struct sockaddr_in));
	if (n < 0) {
		perror("sendto");
	}
	
	return n;

}

static int king_send_heartbeat(int sockfd, int self_id, struct sockaddr_in *paddr) {
	
	U8 buffer[KING_BUFFER_LENGTH] = {0};

	buffer[KING_PROTO_BUFFER_STATUS_IDX] = KING_PROTO_HEARTBEAT_REQ;
	*(int *)(buffer+KING_PROTO_HEARTBEAT_SELFID_IDX) = self_id;

	int n = KING_PROTO_HEARTBEAT_SELFID_IDX + KING_NUMBER_ID_LENGTH;
	n = sendto(sockfd, buffer, n, 0, (struct sockaddr*)paddr, sizeof(struct sockaddr_in));
	if (n < 0) {
		perror("sendto");
	}
	
	return n;
}

static int king_send_connect(int sockfd, int self_id, int other_id, struct sockaddr_in *paddr) {
	
	U8 buffer[KING_BUFFER_LENGTH] = {0};

	buffer[KING_PROTO_BUFFER_STATUS_IDX] = KING_PROTO_CONNECT_REQ;
	*(int *)(buffer+KING_PROTO_CONNECT_SELFID_IDX) = self_id;
	*(int *)(buffer+KING_PROTO_CONNECT_OTHERID_IDX) = other_id;

	int n = KING_PROTO_CONNECT_OTHERID_IDX + KING_NUMBER_ID_LENGTH;
	n = sendto(sockfd, buffer, n, 0, (struct sockaddr*)paddr, sizeof(struct sockaddr_in));
	if (n < 0) {
		perror("sendto");
	}
	
	return n;	
}

static int king_send_p2pconnect(int sockfd, int self_id, struct sockaddr_in *paddr) {

	U8 buffer[KING_BUFFER_LENGTH] = {0};
	
	buffer[KING_PROTO_BUFFER_STATUS_IDX] = NTY_PROTO_P2P_CONNECT_REQ;
	*(int *)(buffer+KING_PROTO_P2P_CONNECT_SELFID_IDX) = self_id;

	int n = KING_PROTO_P2P_CONNECT_SELFID_IDX + KING_NUMBER_ID_LENGTH;
	n = sendto(sockfd, buffer, n, 0, (struct sockaddr*)paddr, sizeof(struct sockaddr_in));
	if (n < 0) {
		perror("sendto");
	}
	
	return n;

}

static int king_send_p2pconnectack(int sockfd, int self_id, struct sockaddr_in *paddr) {

	U8 buffer[KING_BUFFER_LENGTH] = {0};
	
	buffer[KING_PROTO_BUFFER_STATUS_IDX] = NTY_PROTO_P2P_CONNECT_ACK;
	*(int *)(buffer+KING_PROTO_P2P_CONNECT_ACK_SELFID_IDX) = self_id;

	int n = KING_PROTO_P2P_CONNECT_ACK_SELFID_IDX + KING_NUMBER_ID_LENGTH;
	n = sendto(sockfd, buffer, n, 0, (struct sockaddr*)paddr, sizeof(struct sockaddr_in));
	if (n < 0) {
		perror("sendto");
	}
	
	return n;

}


static int king_client_send_message(int sockfd, int self_id, int other_id, struct sockaddr_in *paddr, U8 *msg, int length) {
	U8 buffer[KING_BUFFER_LENGTH] = {0};

	buffer[KING_PROTO_BUFFER_STATUS_IDX] = NTY_RPORO_MESSAGE_REQ; 
	*(int *)(buffer+KING_RPORO_MESSAGE_SELFID_IDX) = self_id;
	*(int *)(buffer+KING_PROTO_MESSAGE_OTHERID_IDX) = other_id;

	memcpy(buffer+KING_RPORO_MESSAGE_CONTENT_IDX, msg, length);

	int n = KING_RPORO_MESSAGE_CONTENT_IDX + length;
	*(U16*)(buffer+KING_PROTO_BUFFER_LENGTH_IDX) = (U16) n;
	
	n = sendto(sockfd, buffer, n, 0, (struct sockaddr*)paddr, sizeof(struct sockaddr_in));
	if (n < 0) {
		perror("sendto");
	}
	return n;
}

static int king_send_messageack(int sockfd, int self_id, struct sockaddr_in *paddr) {

	U8 buffer[KING_BUFFER_LENGTH] = {0};
	
	buffer[KING_PROTO_BUFFER_STATUS_IDX] = NTY_RPORO_MESSAGE_ACK;
	*(int *)(buffer+KING_RPORO_MESSAGE_ACK_SELFID_IDX) = self_id;

	int n = KING_RPORO_MESSAGE_ACK_SELFID_IDX + KING_NUMBER_ID_LENGTH;
	n = sendto(sockfd, buffer, n, 0, (struct sockaddr*)paddr, sizeof(struct sockaddr_in));
	if (n < 0) {
		perror("sendto");
	}
	
	return n;

}




client_table table[KING_CLIENT_MAX] = {0};
int client_count = 0;


static int get_index_by_clientid(int client_id) {
	int i = 0;

	int now_count = client_count;
	for (i = 0;i < now_count;i ++) {
		if (table[i].client_id == client_id) return i;
	}
}


static int king_send_message(int sockfd, int client_id, U8 *buffer, int length) {

	int index = get_index_by_clientid(client_id);
	struct sockaddr_in c_addr;
	c_addr.sin_family = AF_INET;
	array_to_addr(table[index].addr, &c_addr);

	int n = sendto(sockfd, buffer, length, 0, (struct sockaddr*)&c_addr, sizeof(c_addr));
	if (n < 0) {
		perror("sendto");
	}
	return n;
}


static int king_send_notify(int sockfd, int client_id, int self_id) {

	U8 buffer[KING_BUFFER_LENGTH] = {0};

	int index = get_index_by_clientid(self_id);

	buffer[KING_PROTO_BUFFER_STATUS_IDX] = NTY_PROTO_NOTIFY_REQ;
	*(int*)(buffer+KING_PROTO_NOTIFY_SELFID_IDX) = self_id;
	memcpy(buffer+KING_PROTO_NOTIFY_ADDR_IDX, table[index].addr, KING_CLIENT_ADDR_LENGTH);

	index = get_index_by_clientid(client_id);
	struct sockaddr_in c_addr;
	c_addr.sin_family = AF_INET;
	array_to_addr(table[index].addr, &c_addr);

	int n = KING_PROTO_NOTIFY_ADDR_IDX + KING_CLIENT_ADDR_LENGTH;
	n = sendto(sockfd, buffer, n, 0, (struct sockaddr*)&c_addr, sizeof(c_addr));
	if (n < 0) {
		perror("sendto");
	}

	return n;
}





#endif





 

server.c



#include "udp.h"



int king_buffer_parser(int sockfd, U8 *buffer, U32 length, struct sockaddr_in *addr) {

	U8 status = buffer[KING_PROTO_BUFFER_STATUS_IDX];

	printf("king_buffer_parser --> %x\n", status);

	switch (status) {
		case KING_PROTO_LOGIN_REQ: {
#if 1
			int old = client_count;
			int now = old+1;
			if(0 == cmpxchg((UATOMIC*)&client_count, old, now)) { 
				printf("client_count --> %d, old:%d, now:%d\n", client_count, old, now);
				return KING_RESULT_FAILED;
			}
#else
			client_count = client_count+1;
			int now = client_count;
#endif
			U8 array[KING_CLIENT_ADDR_LENGTH] = {0};
			addr_to_array(array, addr);

			printf("login --> %d.%d.%d.%d:%d\n", *(unsigned char*)(&addr->sin_addr.s_addr), *((unsigned char*)(&addr->sin_addr.s_addr)+1),													
				*((unsigned char*)(&addr->sin_addr.s_addr)+2), *((unsigned char*)(&addr->sin_addr.s_addr)+3),													
				addr->sin_port);
			
			table[now].client_id =  *(U32*)(buffer+KING_PROTO_LOGIN_SELFID_IDX);
			memcpy(table[now].addr, array, KING_CLIENT_ADDR_LENGTH);

			break;
		}
		case KING_PROTO_HEARTBEAT_REQ: {

			int client_id = *(unsigned int*)(buffer+KING_PROTO_HEARTBEAT_SELFID_IDX);
			int index = get_index_by_clientid(client_id);

			table[index].stamp = time_genrator();
			
			break;
		}
		case KING_PROTO_CONNECT_REQ: {

			int client_id = *(unsigned int*)(buffer+KING_PROTO_CONNECT_SELFID_IDX);
			int other_id = *(unsigned int*)(buffer+KING_PROTO_CONNECT_OTHERID_IDX);

			king_send_notify(sockfd, other_id, client_id);
			
			break;
		}
		case NTY_RPORO_MESSAGE_REQ: {

			U8 *msg = buffer+KING_RPORO_MESSAGE_CONTENT_IDX;
			int client_id = *(unsigned int*)(buffer+KING_RPORO_MESSAGE_SELFID_IDX);
			int other_id = *(unsigned int*)(buffer+KING_PROTO_MESSAGE_OTHERID_IDX);
			
			printf(" from client:%d --> %s\n", client_id, msg);
#if 0
			king_send_message(sockfd, other_id, buffer, length);
#endif
			break;
		}
	} 

	return KING_RESULT_SUCCESS;
}




int main(int argc, char *argv[]) {

	printf(" This is a UDP Server\n");

	int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
	if (sockfd < 0) {
		perror("socket");
		exit(0);
	}

	struct sockaddr_in addr;
	addr.sin_family = AF_INET;
	addr.sin_port = htons(atoi(argv[1]));
	addr.sin_addr.s_addr = htonl(INADDR_ANY);

	if (bind(sockfd, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
		perror("bind");
		exit(1);
	}

	char buffer[KING_BUFFER_LENGTH] = {0};
	struct sockaddr_in c_addr;
	
	int n;
	int length = sizeof(struct sockaddr_in);

	
	while(1) {
		n = recvfrom(sockfd, buffer, KING_BUFFER_LENGTH, 0, (struct sockaddr*)&c_addr, &length);
		if (n > 0) {
			buffer[n] = 0x0;

			printf("%d.%d.%d.%d:%d say: %s\n", *(unsigned char*)(&c_addr.sin_addr.s_addr), *((unsigned char*)(&c_addr.sin_addr.s_addr)+1),													
				*((unsigned char*)(&c_addr.sin_addr.s_addr)+2), *((unsigned char*)(&c_addr.sin_addr.s_addr)+3),													
				c_addr.sin_port, buffer);

			int ret = king_buffer_parser(sockfd, buffer, n, &c_addr);
			if (ret == KING_RESULT_FAILED) continue;


			buffer[KING_PROTO_BUFFER_STATUS_IDX] += 0x80;
			n = sendto(sockfd, buffer, n, 0, (struct sockaddr*)&c_addr, sizeof(c_addr));
			if (n < 0) {
				perror("sendto");
				break;
			}

		} else if (n == 0) {
			printf("server closed\n");
		} else {
			perror("recv");
			break;
		}
	}

	return 0;
}









 

client.c


#include "udp.h"
#include <pthread.h>


static int status_machine = KING_STATUS_LOGIN;
static int client_selfid = 0x0;

struct sockaddr_in server_addr;

client_table p2p_clients[KING_CLIENT_MAX] = {0};
static int p2p_count = 0;

static int king_client_buffer_parser(int sockfd, U8 *buffer, U32 length, struct sockaddr_in *addr) {

	U8 status = buffer[KING_PROTO_BUFFER_STATUS_IDX];

	switch (status) {
		case NTY_PROTO_NOTIFY_REQ: {
			struct sockaddr_in other_addr;
			other_addr.sin_family = AF_INET;
			array_to_addr(buffer+KING_PROTO_NOTIFY_ADDR_IDX, &other_addr);

			king_send_p2pconnect(sockfd, client_selfid, &other_addr);
			break;
		}
		case NTY_PROTO_P2P_CONNECT_REQ: {
			int now_count = p2p_count++;

			p2p_clients[now_count].stamp = time_genrator();
			p2p_clients[now_count].client_id = *(int*)(buffer+KING_PROTO_P2P_CONNECT_SELFID_IDX);
			addr_to_array(p2p_clients[now_count].addr, addr);
		
			king_send_p2pconnectack(sockfd, client_selfid, addr);
			printf("Enter P2P Model\n");
			status_machine = KING_STATUS_P2P_MESSAGE;

			break;
		}
		case NTY_PROTO_P2P_CONNECT_ACK: {
			int now_count = p2p_count++;
			
			p2p_clients[now_count].stamp = time_genrator();
			p2p_clients[now_count].client_id = *(int*)(buffer+KING_PROTO_P2P_CONNECT_SELFID_IDX);
			addr_to_array(p2p_clients[now_count].addr, addr);
			
			printf("Enter P2P Model\n");
			status_machine = KING_STATUS_P2P_MESSAGE;
			break;
		}
		case NTY_RPORO_MESSAGE_REQ: {

			U8 *msg = buffer+KING_RPORO_MESSAGE_CONTENT_IDX;
			U32 other_id = *(U32*)(buffer+KING_RPORO_MESSAGE_SELFID_IDX);
			
			printf(" from client:%d --> %s\n", other_id, msg);

			king_send_messageack(sockfd, client_selfid, addr);
			//status_machine = KING_STATUS_P2P_MESSAGE;
			
			break;
		}
		case KING_PROTO_LOGIN_ACK: {
			printf(" Connect Server Success\nPlease Enter Message : ");
			status_machine = KING_STATUS_MESSAGE;
			break;
		}
		case KING_PROTO_HEARTBEAT_ACK:
		case KING_PROTO_CONNECT_ACK:
		case NTY_PROTO_NOTIFY_ACK:
			break;
		case NTY_RPORO_MESSAGE_ACK:
			break;
	}
	
}


void* king_recv_callback(void *arg) {

	int sockfd = *(int *)arg;
	struct sockaddr_in addr;
	int length = sizeof(struct sockaddr_in);
	U8 buffer[KING_BUFFER_LENGTH] = {0};

	//printf("king_recv_callback --> enter\n");
	
	while (1) {
		int n = recvfrom(sockfd, buffer, KING_BUFFER_LENGTH, 0, (struct sockaddr*)&addr, &length);
		if (n > 0) {
			buffer[n] = 0;

			king_client_buffer_parser(sockfd, buffer, n, &addr);
		} else if (n == 0) {
			printf("server closed\n");
			close(sockfd);
			break;
		} else if (n == -1) {
			perror("recvfrom");
			close(sockfd);
			break;
		}
	}
}


void *king_send_callback(void *arg) {

	int sockfd = *(int *)arg;
	char buffer[KING_BUFFER_LENGTH] = {0};

	//printf("king_send_callback --> enter\n");
	
	while (1) {

		bzero(buffer, KING_BUFFER_LENGTH);
		
		scanf("%s", buffer);
		//getchar();

		if (status_machine == KING_STATUS_MESSAGE) {

			
			printf(" --> please enter bt : ");
			
			int other_id = buffer[1]-0x30;

			if (buffer[0] == 'C') {
				//printf("king_send_connect");
				king_send_connect(sockfd, client_selfid, other_id, &server_addr);
			} else {
				int length = strlen(buffer);
				king_client_send_message(sockfd, client_selfid, other_id, &server_addr, buffer, length);
			}
		
		} else if (status_machine == KING_STATUS_P2P_MESSAGE) {

			printf(" --> please enter message to send : ");
			
			int now_count = p2p_count;
			struct sockaddr_in c_addr;
			c_addr.sin_family = AF_INET;
			array_to_addr(p2p_clients[now_count-1].addr, &c_addr);

 			int length = strlen(buffer);

			king_client_send_message(sockfd, client_selfid, 0, &c_addr, buffer, length);
		}

	}
}


int main(int argc, char *argv[]) {

	printf(" This is a UDP Client\n");

	if (argc != 4) {
		printf("Usage: %s ip port\n", argv[0]);
		exit(1);
	}

	int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
	if (sockfd < 0) {
		perror("socket");
		exit(1);
	}


	pthread_t thread_id[2] = {0};
	KING_CALLBACK cb[2] = {king_send_callback, king_recv_callback};
	int i = 0;

	for (i = 0;i < 2;i ++) {
		int ret = pthread_create(&thread_id[i], NULL, cb[i], &sockfd);
		if (ret) {
			perror("pthread_create");
			exit(1);
		}
		sleep(1);
	}

	server_addr.sin_family = AF_INET;
	server_addr.sin_port = htons(atoi(argv[2]));
	server_addr.sin_addr.s_addr = inet_addr(argv[1]);
	
	client_selfid = atoi(argv[3]);

	king_send_login(sockfd, client_selfid, &server_addr);

	for (i = 0;i < 2;i ++) {
		pthread_join(thread_id[i], NULL);
	}
	
	return 0;
}




 

实现完成。收工。。。。后期再讲讲webrtc的时候再讲讲p2p以及更多的知识 。。。。。。

  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值