自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

一種通過(guò)Udp進(jìn)行無(wú)確認(rèn)Ip的雙向的通信

網(wǎng)絡(luò) 通信技術(shù)
udp是一種不可靠的通信,但是有些時(shí)候還是會(huì)有使用。今天分享一個(gè)示例:主體邏輯,一個(gè)端口廣播地址,接收到ip地址數(shù)據(jù)后,其他端口基于這個(gè)ip進(jìn)行bind綁定,最后通信,這樣可以保證我們后續(xù)繼續(xù)增加端口交互時(shí)候不需要關(guān)注ip地址綁定的問(wèn)題。

前言

udp是一種不可靠的通信,但是有些時(shí)候還是會(huì)有使用。今天分享一個(gè)示例:主體邏輯,一個(gè)端口廣播地址,接收到ip地址數(shù)據(jù)后,其他端口基于這個(gè)ip進(jìn)行bind綁定,最后通信,這樣可以保證我們后續(xù)繼續(xù)增加端口交互時(shí)候不需要關(guān)注ip地址綁定的問(wèn)題。

主要原理介紹

  • 低通信頻率端口進(jìn)行服務(wù)端IP信息udp廣播,接收端是不固定IP監(jiān)聽(tīng),監(jiān)聽(tīng)主機(jī)任意IP地址的特定端口
  • 接收到廣播通道的ip地址后,與特定IP、port建立tcp或者udp雙向高頻率通信。

下圖是基于 UDP 的 Socket 函數(shù)調(diào)用過(guò)程:

只有接收的時(shí)候需要bind ip和端口

圖片

socket 監(jiān)聽(tīng)所有ip 特定端口代碼:

#define PORT 6000
bzero(&adr_inet, sizeof(adr_inet));
adr_inet.sin_family = AF_INET;
adr_inet.sin_addr.s_addr = htonl(INADDR_ANY);
adr_inet.sin_port = htons(port);
ret = bind(cfd, (struct sockaddr *)&addr, sizeof(addr));

socket綁定的ip為INADDR_ANY 的說(shuō)明:

socket INADDR_ANY 監(jiān)聽(tīng)0.0.0.0地址 socket只綁定端口讓路由表決定傳到哪個(gè)ip

其中INADDR_ANY就是指定地址為0.0.0.0的地址,這個(gè)地址事實(shí)上表示不確定地址,或“所有地址”、“任意地址”。 如果指定ip地址為通配地址(INADDR_ANY),那么內(nèi)核將等到套接字已連接(TCP)或已在套接字上發(fā)出數(shù)據(jù)報(bào)時(shí)才選擇一個(gè)本地IP地址。 一般情況下,如果你要建立網(wǎng)絡(luò)服務(wù)器,則你要通知服務(wù)器操作系統(tǒng):請(qǐng)?jiān)谀车刂?xxx.xxx.xxx.xxx上的某端口 yyyy上進(jìn)行偵聽(tīng),并且把偵聽(tīng)到的數(shù)據(jù)包發(fā)送給我。這個(gè)過(guò)程,你是通過(guò)bind()系統(tǒng)調(diào)用完成的?!簿褪钦f(shuō),你的程序要綁定服務(wù)器的某地址,或者說(shuō):把服務(wù)器的某地址上的某端口占為已用。服務(wù)器操作系統(tǒng)可以給你這個(gè)指定的地址,也可以不給你。

如果你的服務(wù)器有多個(gè)網(wǎng)卡,而你的服務(wù)(不管是在udp端口上偵聽(tīng),還是在tcp端口上偵聽(tīng)),出于某種原因:可能是你的服務(wù)器操作系統(tǒng)可能隨時(shí)增減IP地址,也有可能是為了省去確定服務(wù)器上有什么網(wǎng)絡(luò)端口(網(wǎng)卡)的麻煩 —— 可以要在調(diào)用bind()的時(shí)候,告訴操作系統(tǒng):“我需要在 yyyy 端口上偵聽(tīng),所以發(fā)送到服務(wù)器的這個(gè)端口,不管是哪個(gè)網(wǎng)卡/哪個(gè)IP地址接收到的數(shù)據(jù),都是我處理的?!边@時(shí)候,服務(wù)器則在0.0.0.0這個(gè)地址上進(jìn)行偵聽(tīng)。無(wú)論連接哪個(gè)ip都可以連上的,只要是往這個(gè)端口發(fā)送的所有ip都能連上。

示例代碼:

data_send.c 在端口9001進(jìn)行ip地址的udp廣播以及讀取終端數(shù)據(jù)廣播到7000端口

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <errno.h>
#include <pthread.h>
#include <signal.h>

#define IP "127.0.0.1"
#define
#define

// gcc data_send.c -o data_send -pthread

int cfd = -1;
//接收線程函數(shù)
void *receive(void *pth_arg)
{
int ret = 0;
char name_data[3] = {0};
struct sockaddr_in addr0 = {0};
int addr0_size = sizeof(addr0);
//從對(duì)端ip和端口號(hào)中接收消息,指定addr0用于存放消息
while (1)
{
bzero(name_data, sizeof(name_data));
ret = recvfrom(cfd, name_data, sizeof(name_data), 0, (struct sockaddr *)&addr0, &addr0_size);
if (-1 == ret)
{
fprintf(stderr, "%d, %s :%s", __LINE__, "recv failed", strerror(errno));
exit(-1);
}
else if (ret > 0)
{
printf("\nname = %s ", name_data); //打印對(duì)方的消息和端口號(hào)
printf("ip %s,port %d \n", inet_ntoa(addr0.sin_addr), ntohs(addr0.sin_port));
}
}
}
void *data_send(void *pth_arg)
{
int ret = 0;
char data[] = "IP address";
struct sockaddr_in addr0 = {0};
addr0.sin_family = AF_INET; //設(shè)置tcp協(xié)議族
addr0.sin_port = htons(DATA_PORT); //設(shè)置端口號(hào)
addr0.sin_addr.s_addr = htonl(INADDR_ANY); //設(shè)置ip地址
//發(fā)送消息
while (1)
{
ret = sendto(cfd, (void *)data, sizeof(data), 0, (struct sockaddr *)&addr0, sizeof(addr0));
sleep(1);
if (-1 == ret)
{
fprintf(stderr, "%d, %s :%s", __LINE__, "sendto failed", strerror(errno));
exit(-1);
}
}
}

int main()
{
int ret = -1;
//創(chuàng)建tcp/ip協(xié)議族,指定通信方式為無(wú)鏈接不可靠的通信
cfd = socket(AF_INET, SOCK_DGRAM, 0);
if (-1 == cfd)
{
fprintf(stderr, "%d, %s :%s", __LINE__, "socket failed", strerror(errno));
exit(-1);
}

//進(jìn)行端口號(hào)和ip的綁定
struct sockaddr_in addr;
addr.sin_family = AF_INET; //設(shè)置tcp協(xié)議族
addr.sin_port = htons(PORT); //設(shè)置端口號(hào)
addr.sin_addr.s_addr = inet_addr(IP); //設(shè)置ip地址
ret = bind(cfd, (struct sockaddr *)&addr, sizeof(addr));

if (-1 == ret)
{
fprintf(stderr, "%d, %s :%s", __LINE__, "bind failed", strerror(errno));
exit(-1);
}

//創(chuàng)建線程函數(shù),用于處理數(shù)據(jù)接收
pthread_t id,data_send_id;
ret = pthread_create(&id, NULL, receive, NULL);
if (-1 == ret)
{
fprintf(stderr, "%d, %s :%s", __LINE__, "pthread_create failed", strerror(errno));
exit(-1);
}
// pthread_join(id,NULL);
ret = pthread_create(&data_send_id, NULL, data_send, NULL);
if (-1 == ret)
{
fprintf(stderr, "%d, %s :%s", __LINE__, "pthread_create failed", strerror(errno));
exit(-1);
}

struct sockaddr_in addr0;
addr0.sin_family = AF_INET; //設(shè)置tcp協(xié)議族
addr0.sin_port = htons(7000); //設(shè)置端口號(hào)
addr0.sin_addr.s_addr = inet_addr(IP); //設(shè)置ip地址

char name_send[3] = {0};
//發(fā)送消息
while (1)
{
bzero(name_send, sizeof(name_send));
printf("send name:");
scanf("%s", name_send);

//發(fā)送消息時(shí)需要綁定對(duì)方的ip和端口號(hào)
ret = sendto(cfd, (void *)name_send, sizeof(name_send), 0, (struct sockaddr *)&addr0, sizeof(addr0));
if (-1 == ret)
{
fprintf(stderr, "%d, %s :%s", __LINE__, "accept failed", strerror(errno));
exit(-1);
}
}
return 0;
}

data_process.c 進(jìn)行端口9001的ip數(shù)據(jù)的捕獲,當(dāng)接收到ip數(shù)據(jù)后,綁定廣播的ip地址進(jìn)行數(shù)據(jù)的收發(fā),這里用的是udp接收大家也可以試試tcp交互。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <errno.h>
#include <pthread.h>
#include <signal.h>

#define IP "127.0.0.1"
#define
#define
// typedef uint32_t in_addr_t;

// gcc data_process.c -o data_process -pthread
int cfd = -1,data_fd = -1;
uint32_t receive_ip = -1;
void *receive(void *pth_arg)
{
int ret = 0;
char name_data[3] = {0};
struct sockaddr_in addr0 = {0};
int addr0_size = sizeof(addr0);
while (1)
{
printf("receive:");
bzero(name_data, sizeof(name_data));
ret = recvfrom(cfd, name_data, sizeof(name_data), 0, (struct sockaddr *)&addr0, &addr0_size);
if (-1 == ret)
{
fprintf(stderr, "%d, %s :%s", __LINE__, "recv failed", strerror(errno));
exit(-1);
}
else if (ret > 0)
{
printf("\nname = %s ", name_data);
printf("ip %s,port %d \n", inet_ntoa(addr0.sin_addr), ntohs(addr0.sin_port));
}
}
}
void *data_receive(void *pth_arg)
{
int ret = 0;
char name_data[10] = {0};
struct sockaddr_in addr0 = {0};
int addr0_size = sizeof(addr0);
while (1)
{
bzero(name_data, sizeof(name_data));
ret = recvfrom(data_fd, name_data, sizeof(name_data), 0, (struct sockaddr *)&addr0, &addr0_size);
if (-1 == ret)
{
fprintf(stderr, "%d, %s :%s", __LINE__, "recv failed", strerror(errno));
exit(-1);
}
else if (ret > 0)
{
printf("\nname = %s ", name_data);
printf("ip %s,port %d \n", inet_ntoa(addr0.sin_addr), ntohs(addr0.sin_port));
receive_ip = addr0.sin_addr.s_addr;
char buf[20] = { 0 };
inet_ntop(AF_INET, &receive_ip, buf, sizeof(buf));
printf("receive_ip ip = %s ", buf);
// printf("receive_ip ip = %s ", inet_ntop(receive_ip));
break;
}
}
}
int main()
{
int ret = -1;
data_fd = socket(AF_INET, SOCK_DGRAM, 0);
if (-1 == data_fd)
{
fprintf(stderr, "%d, %s :%s", __LINE__, "socket failed", strerror(errno));
exit(-1);
}

struct sockaddr_in addr;
addr.sin_family = AF_INET; //設(shè)置tcp協(xié)議族
addr.sin_port = htons(DATA_PORT); //設(shè)置端口號(hào)
addr.sin_addr.s_addr = inet_addr(IP); //設(shè)置ip地址
ret = bind(data_fd, (struct sockaddr *)&addr, sizeof(addr));
if (-1 == ret)
{
fprintf(stderr, "%d, %s :%s", __LINE__, "bind failed", strerror(errno));
exit(-1);
}
pthread_t receive_id;
ret = pthread_create(&receive_id, NULL, data_receive, NULL);
if (-1 == ret)
{
fprintf(stderr, "%d, %s :%s", __LINE__, "pthread_create failed", strerror(errno));
exit(-1);
}
pthread_join(receive_id,NULL);

cfd = socket(AF_INET, SOCK_DGRAM, 0);
if (-1 == cfd)
{
fprintf(stderr, "%d, %s :%s", __LINE__, "socket failed", strerror(errno));
exit(-1);
}

struct sockaddr_in addr1;
addr1.sin_family = AF_INET; //設(shè)置tcp協(xié)議族
addr1.sin_port = htons(PORT); //設(shè)置端口號(hào)
addr1.sin_addr.s_addr = receive_ip; //設(shè)置ip地址
char buf[20] = { 0 };
inet_ntop(AF_INET, &receive_ip, buf, sizeof(buf));
printf("ip = %s ", buf);

ret = bind(cfd, (struct sockaddr *)&addr1, sizeof(addr1));
if (-1 == ret)
{
fprintf(stderr, "%d, %s :%s", __LINE__, "bind failed", strerror(errno));
exit(-1);
}

pthread_t id;
ret = pthread_create(&id, NULL, receive, NULL);
if (-1 == ret)
{
fprintf(stderr, "%d, %s :%s", __LINE__, "pthread_create failed", strerror(errno));
exit(-1);
}
pthread_join(id,NULL);

struct sockaddr_in addr0;
addr0.sin_family = AF_INET; //設(shè)置tcp協(xié)議族
addr0.sin_port = htons(6000); //設(shè)置端口號(hào)
addr0.sin_addr.s_addr = inet_addr(IP); //設(shè)置ip地址

char name_send[3] = {0};
while (1)
{
bzero(name_send, sizeof(name_send));
printf("send name:");
scanf("%s", name_send);

ret = sendto(cfd, (void *)name_send, sizeof(name_send), 0, (struct sockaddr *)&addr0, sizeof(addr0));
if (-1 == ret)
{
fprintf(stderr, "%d, %s :%s", __LINE__, "accept failed", strerror(errno));
exit(-1);
}
}
return 0;
}

一個(gè)終端捕獲數(shù)據(jù),sudo tcpdump -i lo portrange 5000-8000 -vv -XX -nn,另外兩個(gè)終端進(jìn)行數(shù)據(jù)交互

圖片

結(jié)語(yǔ)

這就是我自己的一些udp設(shè)計(jì)思路的分享。如果大家有更好的想法和需求,也歡迎大家加我好友交流分享哈。

作者:良知猶存,白天努力工作,晚上原創(chuàng)公號(hào)號(hào)主。公眾號(hào)內(nèi)容除了技術(shù)還有些人生感悟,一個(gè)認(rèn)真輸出內(nèi)容的職場(chǎng)老司機(jī),也是一個(gè)技術(shù)之外豐富生活的人,攝影、音樂(lè) and 籃球。

責(zé)任編輯:武曉燕 來(lái)源: 羽林君
相關(guān)推薦

2013-12-04 13:34:44

2021-10-26 16:49:34

系統(tǒng)性能定位

2009-04-11 15:12:24

2020-12-23 10:10:23

Pythonweb代碼

2022-06-22 09:44:41

Python文件代碼

2022-07-07 10:33:27

Python姿勢(shì)代碼

2020-12-09 10:15:34

Pythonweb代碼

2022-09-22 08:18:28

JavaAssistJboss開(kāi)源

2023-09-27 14:32:44

2018-02-27 10:36:20

物聯(lián)網(wǎng)無(wú)線通信應(yīng)用程序

2022-05-12 11:08:31

PHPJava開(kāi)發(fā)

2018-12-14 14:30:12

安全檢測(cè)布式系測(cè)試

2017-03-13 11:30:39

2021-09-09 10:06:09

鴻蒙HarmonyOS應(yīng)用

2020-07-30 13:00:00

Python面部識(shí)別智能

2017-07-05 14:09:04

系統(tǒng)設(shè)計(jì)與架構(gòu)java云計(jì)算

2011-03-01 09:43:13

MapReduce架構(gòu)

2022-06-23 07:05:46

跳板機(jī)服務(wù)器PAM

2012-03-21 09:54:00

Gzip

2010-06-09 16:17:20

TCP IP協(xié)議網(wǎng)絡(luò)故
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)