Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

Decentralized Network Design-implementation of P2P

2025-03-26 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Servers >

Share

Shulou(Shulou.com)06/02 Report--

As the blockchain becomes more and more popular, decentralized network design is once again brought to the technical staff. Here I use a very popular language to help you understand the foundation of decentralized network design-network penetration. Then use the code to achieve penetration. If the explanation is not in place, you are welcome to throw bricks. The code is here: https://github.com/wangbojing/P2PServer

In a network with centralized servers, clients, servers, and gateways constitute the network topology diagram. As shown in figure 1 below: since there are many subsequent noun concepts, the first three chapters should be unified here: all terminal machines become clients, and different clients are distinguished by uppercase letters. ); the applications running above the client are called client programs, and different applications are distinguished by different numbers. ). The physical machine that acts as the server is called the server, and the program running on the server is called the service program, and each topology component in the following text has only one IP address. The components that provide public network IP services to clients are called gateways.

Figure 1 Network topology diagram of a centralized server

Mapping from the gateway to the network structure in the client requires the introduction of a concept of NAT. What NAT? It is called network address translation in Chinese, and it is used to be called network address mapping. Why do you need network address mapping? It needs to be said that the IPV4 network address has been used up, and the use of all IPV6 will cause many terminal devices that only support IPV4 to fail to use properly, so network address mapping arises at the historic moment to endure humiliation. There will be what we now call Internet penetration. How on earth is it mapped? The network address mapping is shown in figure 2. The client program uses 192.168.0.234virtual 7890 to send data. Through the network address mapping of the gateway, it is converted to 112.93.116.102virtual 6834 on the public network, which is recognized by everyone on the Internet. At this time, the ip and port of the client program used on the public network are replaced by 112.93.116.102 fre6834. Here you should understand what kind of species NAT is.

Figure 2 Network address mapping

In order to maintain the novice gospel, the attitude of conscience in the industry. What is penetration? Because NAT is initiated by a client program, a new temporary license created by the network in order to maintain communications may be withdrawn at any time, and the license after re-launch is different. As a result, the outside world knew in time that this temporary license was useless. So we need to make a hole in the gateway through penetration to serve the outside world. So what does NAT have to do with penetration? It is because of NAT that you need to interpenetrate. If you have an IP address for each client of IPV6, you don't need to find the client directly.

Network address mapping

Due to the inconsistent security requirements of gateways, there are four different ways of NAT. Elaborate separately:

The first fully tapered NAT is called Full Cone NAT in English. As shown in the full conical NAT in figure 3, the client program (192.168.0.234) communicates with server A (13.44.178.98), the public network address of the temporary license generated by the address translation of the gateway (112.93.116.102), and server B (157.78.13.156), which sends data to the public address (112.93.116.102). If the client program (192.168.0.234virtual 7890) can receive the data sent by server B (157.78.13.156virtual 23456), the NAT mapping is a completely conical NAT.

Fig. 3 fully tapered NAT

The second kind of restricted cone NAT is called RestrictedCone NAT in English. In figure 3, in the fully tapered NAT, if the client program (192.168.0.234 NAT) cannot receive the data sent by server B (157.78.13.156 NAT 23456), the mapping relationship is a restricted cone NAT.

The third type of port restricted conical NAT is called Port RestrictedCone NAT in English. The client program (192.168.0.234Drex7890) sends data to the service program (13.44.178.98), the address generated by the gateway through network address translation (112.93.116.102), and another service program in the same server (13.44.178.178virtual 9801) sends data to the gateway address (112.93.116.102) if the client program (192.168.0.234) can receive it. To restrict the conical NAT, the port restricts the conical NAT if the client program (192.168.0.234virtual 7890) cannot receive it.

For all conical NAT, the gateway address translation address is the same (112.93.116.102 NAT 6834) when the data sent by the client program (192.168.0.234glaze 7890) is the same, so why can't the client program receive the data of service program B (13.44.178.989801) in the restricted conical NAT in figure 4? Because there is no client program (192.168.0.234glaze 7890) to service program B (13.44.178.98), the service program (13.44.178.98) is sent directly to the gateway (112.93.116.10268) and is discarded by the gateway.

Fig. 4 restricted conical NAT

The fourth symmetrical NAT, in English, is called Symmetric NAT. As shown in the symmetrical NAT in figure 5, when the client program (192.168.0.234purl 7890) sends data to two different servers (13.44.178.98pur.9800) and (157.78.13.156frex23456), the gateway generates different network address mappings (112.93.116.102 frex6834) and (112.93.116.102 frex6835). This is the process of sending data out for the entire NAT network, and the received data is consistent with the port limit cone NAT.

Fig. 5 symmetrical NAT

This section introduces the concepts of three tapered NAT and symmetrical NAT, and I'm sure you still don't know how the NAT type relates to how to penetrate the gateway.

Penetrating analysis

How to penetrate the gateway to achieve decentralization, as shown in figure 6 through the network NAT topology diagram

Ideally, in NAT 1, the client (192.168.0.234) knows the network mapping address (157.123.80.165) of the client (192.168.2.168) in NAT 2, and sends data to the network map (157.123.80.165), and the client (192.168.2.168) can receive the data. The client program in NAT 2 (192.168.2.168 NAT 2786) also knows the network mapping address of the client program in NAT 1, and sends data to its network mapping address (112.93.116.102 6834), and can also receive the data. At this time, for the server, it does not play the role of data transfer, at this time, the client program (192.168.0.234virtual 7890) and the client program (192.168.2.168freed 2786) can send and receive data to each other, and the service program (13.44.178.98 purge 9800) has no effect. For the client program, it has been decentralized.

This is only in the theoretical situation, now the specific implementation steps and the combination of the four NAT types to analyze.

First: NAT 1 is fully tapered NAT,NAT 2 is any NAT mode, as shown in figure 7 full tapered NAT penetration, green font order.

The client program (192.168.0.234glaze 7890) first sends a connection request to the service program, notifying the service program that it needs to connect to the client program (192.168.2.168frex2786).

After receiving the connection request, the service program sends a message to the client program (192.168.2.168), notifies the client program (192.168.2.168), and sends a P2P connection request to the gateway (112.93.116.102).

The client (192.168.2.168) sends a P2P connection request to the gateway (112.93.116.102). Because the NAT1 is a fully tapered NAT, the client (192.168.0.234) can receive the request from the client (192.168.2.168).

After receiving the P2P connection request, the client program (192.168.0.234glaze 7890) parses the IP address and port of the request sender client program (192.168.2.168ghan2786) from the request data, and immediately returns a confirmation message. At this point, both parties enter the P2P penetration mode.

However, there is one thing to note here: when NAT2 is symmetrical NAT, in step 3, the gateway will generate another port with the same IP address, which is used to communicate with the network in NAT1; in step 4, the address of the data returned by the client program (192.168.0.234NAT1 7890) is the newly generated port.

Fig. 7 Penetration of fully tapered NAT

The second: NAT 1 is a restricted conical NAT or a port restricted conical NAT (the two conical NAT modes are the same, so they are not explained separately), and NAT 2 is a conical NAT. As shown in figure 8, which restricts the penetration of a tapered NAT

The client program (192.168.0.234glaze 7890) sends a connection request to the service program, notifying the service program that it needs to connect to the client program (192.168.2.168purr 2786).

After receiving the connection request, the service program sends a message to the client program (192.168.2.168), notifies the client program (192.168.2.168), and sends a P2P connection request to the gateway (112.93.116.102).

The client (192.168.2.168) sends a P2P connection request to the gateway (112.93.116.102). Because the NAT1 restricts the conical NAT, the client (192.168.0.234) cannot receive the sent P2P connection request. The final step is to generate a new record of the NAT destination address at the NAT2 gateway (157.123.80.165NAT). Cooperate with the next 6 steps.

The client program (192.168.2.168) the reminder service program notifies the client program (192.168.0.234Flux 7890).

The service program immediately informs the client program (192.168.0.234 7890) to send the request to the NAT2 gateway (157.123.80.165 6954).

The client (192.168.0.234) sends a P2P connection request to the gateway (157.123.80.165). Since the request has just been made in three steps, the gateway will consider it to be a response returned in three steps, so it is possible to send the P2P connection request to the client (192.168.2.168virtual 2786).

After receiving the P2P connection request, the client program (192.168.2.168) immediately returns a confirmation message to the parsed IP address and port of the P2P connection request packet. This confirmation message can be successfully completed to the client program (192.168.0.234frex7890). By this time, the gateway has penetrated and P2P has been established.

Figure 8 limiting the penetration of a tapered NAT

The third kind: NAT1 restricts conical NAT,NAT2 to symmetrical NAT. This is shown in figure 8, which restricts the penetration of tapered NAT.

There are some differences between steps 3 and 6 and NAT2 to limit the conical NAT, and the rest of the steps are the same.

Step 3: the client (192.168.2.168) sends a P2P connection request to the gateway (112.93.116.102). Because NAT2 is a symmetric network, a port is regenerated for communication to the gateway (112.93.116.102). There is no way to accurately know the newly generated port. You can only guess.

Step 6: send data to the gateway (157.123.80.165: guess the port).

An idea is provided here to improve the accuracy of guessing. The service program uses two ports (9800 before, and a new 9801 is added). Since the gateway NAT assigns ports sequentially, a request is sent to the service program (port 9801) in step 4. Because the interval between step 3 and step 4 is short, the new port generated in step 3 at the gateway (157.123.80.165) is smaller than that in step 4. In order to improve the accuracy of the guess.

It is believed that there is a clear concept of the specific steps of penetration, how to accurately judge the current type of NAT?

NAT classification

In fact, the concept of network address mapping has been introduced and classified, which is described here in a more computerized language.

The first is to detect whether the gateway of the current client program is a fully tapered NAT, as shown in figure 9, which detects a full conical NAT

Fig. 9 Detection of full conical NAT

First, the availability of the Udp is tested, and the client program (192.168.0.234 7890) uses an 300ms timer to send the Udp request packet to server A. Wait for server A to return confirmation data. If you send a request several times and do not get the confirmation data from the server, it is considered that the Udp cannot be informed, and the whole detection process is introduced. If the acknowledgement data is received, the timer is also used to send another kind of request data to require server B to send data to the gateway (112.93.116.102 Gateway 6834). If the data from server B is received, it is considered to be a complete cone network. If it is not received, restrict the conical NAT.

Second, detect the limited cone network, as shown in figure 10.

Figure 10 Detection limit conical NAT

The client program (192.168.0.234glaze 7890) periodically sends packets to service program An and requires the service program to send packets to the gateway from another port (112.93.116.102 frex6834). If the client program (192.168.0.234 7890) receives a response, the NAT is a restricted conical NAT. If there is no response to multiple operations, symmetrical NAT detection is performed.

Third, check whether the gateway of the current client program is a symmetric NAT, as shown in figure 9

The client program (192.168.0.234virtual 7890) sends data packets to server A (13.44.178.98) and server B (157.78.13.156) to see if the () IP address and port received by the two servers are the same. If it is inconsistent, it is a symmetrical network. If consistent, the network limits the conical NAT for the port.

The following is the penetration code that implements the complete conical network

Udp.h

/ * * Author: WangBoJing * email: 1989wangbojing@gmail.com * github: https://github.com/wangbojing * / # ifndef _ _ UDP_H__#define _ _ UDP_H__#include # include typedef unsigned int U32enttypedef unsigned short U16 include 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 4typedef struct _ CLIENT_TABLE {U8 addr [king _ CLIENT_ADDR_LENGTH]; U32 client_id; long st} 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 Compact * 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_IDXstatic unsigned long cmpxchg (UATOMIC * addr Unsigned long _ old, unsigned long _ new) {U8 res _ _ asm__ volatile ("lock; cmpxchg% 3,% 1 static long time_genrator 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 lTimeSt} static int addr_to_array (U8 * array, struct sockaddr_in * p_addr) {int I = 0; for (I = 0

< 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 = 0polii)

< 4;i ++) { *((unsigned char*)(&p_addr->

Sin_addr.s_addr) + I) = array [I];} for (I = 0

< 2;i ++) { *((unsigned char*)(&p_addr->

Sin_port) + I) = array [4i];}} 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 udp_client.c /* * Author: WangBoJing * email: 1989wangbojing@gmail.com * github: https://github.com/wangbojing */#include "udp.h"#include 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') {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 = p2pclients; struct sockaddr_in censor addr; c_addr.sin_family = AF_INET; array_to_addr (p2pclients [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;} udp_server.c /* * Author: WangBoJing * email: 1989wangbojing@gmail.com * github: https://github.com/wangbojing */#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;}

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Servers

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report