Linux网络编程四、UDP,广播和组播
一、UDP
UDP:是一个支持无连接的传输协议,全称是用户数据包协议(User Datagram Protocol)。UDP协议无需像TCP一样要建立连接后才能发送封装的IP数据报,也是因此UDP相较于TCP效率更高一些,但是由于没有建立连接,UDP只管发送数据,不管数据是否被接收,所以UDP传输数据是不安全的,容易丢包。
通信流程:
服务端
1、创建通信用套接字:socket(AF_INET, SOCK_DGRAM, 0); 和TCP不同之处在于第二个参数改为SOCK_DGRAM。
2、绑定套接字:bind(...);
3、通信:接收数据,recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);。发送数据,sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, const socklen_t *addrlen); 第五个参数都是另一端的信息,src_addr是传出参数。
客户端同服务端。
二、广播
广播:在IP子网内广播数据包,所有在子网内部的主机都将收到这些数据包。广播的使用范围仅在本地子网中,通过路由器控制广播的传输。广播地址:xxx.xxx.xxx.255。
通信流程:
1、创建并绑定套接字,同UDP。
2、初始化客户端信息,主要是设置客户端ip为广播地址。
3、开放服务器的广播权限:int flag = 1; setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &flag, sizeof(flag));
4、给客户端(子网内的主机)发送数据。
客户端同UDP,不能向服务器发送数据。
//server//
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <arpa/inet.h> int main(int argc, const char* argv[])
{
// 创建套接字
int fd = socket(AF_INET, SOCK_DGRAM, );
if(fd == -)
{
perror("socket error");
exit();
} // 绑定server的iP和端口
struct sockaddr_in serv;
memset(&serv, , sizeof(serv));
serv.sin_family = AF_INET;
serv.sin_port = htons(); // server端口
serv.sin_addr.s_addr = htonl(INADDR_ANY);
int ret = bind(fd, (struct sockaddr*)&serv, sizeof(serv));
if(ret == -)
{
perror("bind error");
exit();
} // 初始化客户端地址信息
struct sockaddr_in client;
memset(&client, , sizeof(client));
client.sin_family = AF_INET;
client.sin_port = htons(); // 客户端要绑定的端口
// 使用广播地址给客户端发数据
inet_pton(AF_INET, "192.168.123.255", &client.sin_addr.s_addr); // 给服务器开放广播权限
int flag = ;
setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &flag, sizeof(flag)); // 通信
while()
{
// 一直给客户端发数据
static int num = ;
char buf[] = {};
sprintf(buf, "hello, udp == %d\n", num++);
int ret = sendto(fd, buf, strlen(buf)+, , (struct sockaddr*)&client, sizeof(client));
if(ret == -)
{
perror("sendto error");
break;
} printf("server == send buf: %s\n", buf); sleep();
} close(fd); return ;
}
//client//
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <arpa/inet.h> int main(int argc, const char* argv[])
{
int fd = socket(AF_INET, SOCK_DGRAM, );
if(fd == -)
{
perror("socket error");
exit();
} // 绑定iP和端口
struct sockaddr_in client;
memset(&client, , sizeof(client));
client.sin_family = AF_INET;
client.sin_port = htons();
inet_pton(AF_INET, "0.0.0.0", &client.sin_addr.s_addr);
int ret = bind(fd, (struct sockaddr*)&client, sizeof(client));
if(ret == -)
{
perror("bind error");
exit();
} // 接收数据
while()
{
char buf[] = {};
int len = recvfrom(fd, buf, sizeof(buf), , NULL, NULL);
if(len == -)
{
perror("recvfrom error");
break;
} printf("client == recv buf: %s\n", buf);
} close(fd); return ;
}
三、组播
组播:在发送者和每一接收者之间实现点对多点网络连接。如果一台发送者同时给多个接收者传输相同的数据,也只需复制一份相同的数据包。它提高了数据传送效率,减少了骨干网络出现拥塞的可能性。组播不同于广播的地方在于其不局限于局域网,而且其效率比广播更高。
组播地址:224.0.0.0~224.0.0.255,预留组播地址(永久组地址),224.0.0.0保留不做分配,其它地址供路由器协议使用。224.0.1.0~224.0.1.255,公用组播地址,可以用于Internet,需要申请。224.0.2.0~238.255.255.255,用户可用组播地址(临时组地址),全网有效。239.0.0.0~239.255.255.255,本地管理组播地址, 仅在特定的本地范围内有效。
通信流程:
1、创建并绑定套接字,同UDP。
2、初始化客户端地址信息,设置组播地址和客户端要绑定的端口。
3、开放组播权限
// 给服务器开放组播权限
struct ip_mreqn flag;
// init flag
inet_pton(AF_INET, "239.0.0.10", &flag.imr_multiaddr.s_addr); // 组播地址
inet_pton(AF_INET, "0.0.0.0", &flag.imr_address.s_addr); // 本地IP
flag.imr_ifindex = if_nametoindex("ens33");
setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, &flag, sizeof(flag));
客户端,绑定端口要与服务端设置的相一致
客户端加入到组播地址
// 加入到组播地址
struct ip_mreqn fl;
inet_pton(AF_INET, "239.0.0.10", &fl.imr_multiaddr.s_addr);
inet_pton(AF_INET, "0.0.0.0", &fl.imr_address.s_addr);
fl.imr_ifindex = if_nametoindex("ens33");
setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &fl, sizeof(fl));
//server//
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <arpa/inet.h>
#include <net/if.h> int main(int argc, const char* argv[])
{
// 创建套接字
int fd = socket(AF_INET, SOCK_DGRAM, );
if(fd == -)
{
perror("socket error");
exit();
} // 绑定server的iP和端口
struct sockaddr_in serv;
memset(&serv, , sizeof(serv));
serv.sin_family = AF_INET;
serv.sin_port = htons(); // server端口
serv.sin_addr.s_addr = htonl(INADDR_ANY);
int ret = bind(fd, (struct sockaddr*)&serv, sizeof(serv));
if(ret == -)
{
perror("bind error");
exit();
} // 初始化客户端地址信息
struct sockaddr_in client;
memset(&client, , sizeof(client));
client.sin_family = AF_INET;
client.sin_port = htons(); // 客户端要绑定的端口
// 使用组播地址给客户端发数据
inet_pton(AF_INET, "239.0.0.10", &client.sin_addr.s_addr); // 给服务器开放组播权限
struct ip_mreqn flag;
// init flag
inet_pton(AF_INET, "239.0.0.10", &flag.imr_multiaddr.s_addr); // 组播地址
inet_pton(AF_INET, "0.0.0.0", &flag.imr_address.s_addr); // 本地IP
flag.imr_ifindex = if_nametoindex("ens33");
setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, &flag, sizeof(flag)); // 通信
while()
{
// 一直给客户端发数据
static int num = ;
char buf[] = {};
sprintf(buf, "hello, udp == %d\n", num++);
int ret = sendto(fd, buf, strlen(buf)+, , (struct sockaddr*)&client, sizeof(client));
if(ret == -)
{
perror("sendto error");
break;
} printf("server == send buf: %s\n", buf); sleep();
} close(fd); return ;
}
//client//
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <arpa/inet.h>
#include <net/if.h> int main(int argc, const char* argv[])
{
int fd = socket(AF_INET, SOCK_DGRAM, );
if(fd == -)
{
perror("socket error");
exit();
} // 绑定iP和端口
struct sockaddr_in client;
memset(&client, , sizeof(client));
client.sin_family = AF_INET;
client.sin_port = htons(); // ........
inet_pton(AF_INET, "0.0.0.0", &client.sin_addr.s_addr);
int ret = bind(fd, (struct sockaddr*)&client, sizeof(client));
if(ret == -)
{
perror("bind error");
exit();
} // 加入到组播地址
struct ip_mreqn fl;
inet_pton(AF_INET, "239.0.0.10", &fl.imr_multiaddr.s_addr);
inet_pton(AF_INET, "0.0.0.0", &fl.imr_address.s_addr);
fl.imr_ifindex = if_nametoindex("ens33");
setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &fl, sizeof(fl)); // 接收数据
while()
{
char buf[] = {};
int len = recvfrom(fd, buf, sizeof(buf), , NULL, NULL);
if(len == -)
{
perror("recvfrom error");
break;
} printf("client == recv buf: %s\n", buf);
} close(fd); return ;
}
Linux网络编程四、UDP,广播和组播的更多相关文章
- linux网络编程之二-----多播(组播)编程
多播编程实例 服务器端 下面是一个多播服务器的例子.多播服务器的程序设计很简单,建立一个数据包套接字,选定多播的IP地址和端口,直接向此多播地址发送数据就可以了.多播服务器的程序设计,不需要服务器加入 ...
- Linux网络编程(四)
在linux网络编程[1-3]中,我们编写的网络程序仅仅是为了了解网络编程的基本步骤,实际应用当中的网络程序并不会用那样的.首先,如果服务器需要处理高并发访问,通常不会使用linux网络编程(三)中那 ...
- Linux网络编程:UDP Socket编程范例
TCP协议提供的是一种可靠的,复杂的,面向连接的数据流(SOCK_STREAM)传输服务,它通过三段式握手过程建立连接.TCP有一种"重传确认"机制,即接收端收到数据后要发出一个肯 ...
- Linux 网络编程四(socket多线程升级版)
//网络编程--客户端 #include <stdio.h> #include <stdlib.h> #include <string.h> #include &l ...
- python网络编程(UDP+广播)
UDP广播案例,一端发送,多端接受: 发送端: # UDP广播案例 from socket import * from time import sleep # 设定目标地址 dest=('176.21 ...
- UDP广播,组播服务器
广播 #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/ ...
- Linux网络编程:UDP实现可靠的文件传输
我们知道,用TCP实现文件传输很简单.相对于TCP,因为UDP是面向无连接.不可靠的传输协议,所以我们需要考虑丢包和后发先至(包的顺序)的问题,所以我们想要实现UDP传输文件,则需要解决这两个问题.方 ...
- linux网络编程笔记——UDP
目前这部分代码会出现阻塞问题,暂时尚未解决 #include "udp.h" #include <stdio.h> #include <string.h> ...
- Linux 网络编程(UDP)
客户端代码 #include<stdio.h> #include<stdlib.h> #include<string.h> #include<sys/sock ...
随机推荐
- 关于Windows下的访问控制模型
在探索Windows操作系统的过程中,发现很多有意思 的东西. Windows下的访问控制模型也是我在Github上浏览代码时,无意中发现的. 项目地址 https://github.com/Krut ...
- C# DataGridView 动态添加列和行
https://blog.csdn.net/alisa525/article/details/7350471 dataGridView1.ReadOnly = true ; //禁用编辑功能 ...
- 天然气水电行业专用抄表器PDA现场打印通知单
传统的抄表工作是使用卡片记录,抄表工人不仅需要背着厚厚的卡片进行记录,回到电力局还需要有专门人员进行电脑录入,浪费了大量人力物力,而且各个环节上出错率比较高.电力专用抄表器的广泛应用使得电力抄表工作变 ...
- 【转】HTTP响应状态码参考簿
HTTP响应状态码参考簿 http状态返回代码 1xx(临时响应)表示临时响应并需要请求者继续执行操作的状态代码. http状态返回代码 代码 说明100 (继续) 请求者应当继续提出请求. ...
- Java Data JPA +hibernate 保存或者是查询遇到的坑
由于项目需求,接触了Java Data JPA +hibernate,它的调用方式是controller调用service,service有实现的接口serviceimpl,serviceimpl调用 ...
- 利用shell命令分析服务器日志
在没有专业日志分析系统的情况下,我们有时需要对日志进行简单的分析,下面列出一些常用的shell命令分析日志的方法,一定要收藏 1.查看有多少个ip访问 awk '{print $1}' log_f ...
- PAT基础级-钻石段位样卷2-7-6 帅到没朋友 (20 分)
当芸芸众生忙着在朋友圈中发照片的时候,总有一些人因为太帅而没有朋友.本题就要求你找出那些帅到没有朋友的人. 输入格式: 输入第一行给出一个正整数N(≤),是已知朋友圈的个数:随后N行,每行首先给出一个 ...
- ubuntu安装anaconda3+tensorflow(cpu)+pycharm(windows几乎一样)
网上乱七八糟有的都是别人怎么写自己也怎么写,其实很简单. 首先是anaconda3的安装: 直接上官网:https://www.anaconda.com/download/ 下载下来之后进入文件所在目 ...
- 三维视觉、SLAM方向全球顶尖实验室汇总
本文作者 任旭倩,公众号:计算机视觉life,编辑成员 欧洲 英国伦敦大学帝国理工学院 Dyson 机器人实验室 http://www.imperial.ac.uk/dyson-robotics-la ...
- 利用k8s实现HPA
如何利用kubernetes实现应用的水平扩展(HPA) 云计算具有水平弹性的特性,这个是云计算区别于传统IT技术架构的主要特性.对于Kubernetes中的POD集群来说,HPA就是实现这种水平伸缩 ...