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 ...
随机推荐
- centos安装rocketMQ
1.下载安装包 http://rocketmq.apache.org/release_notes/ 这里选择 4.4.0 版本,点击进去 可以选择源码包或者二进制文件,这里选择二进制文件(ps:如果选 ...
- win10重装系统修改信息
在安装win10系统之前要先进行ahci硬盘模式更改 ,以防止win10系统安装完成后出现蓝屏现象,那么如何进行ahci硬盘模式bios设置呢?今天我们就以映泰主板为大家介绍u盘装win10系统硬盘模 ...
- 关于Ad-hoc
Ad-hoc是wifi的一个模式,依托普通无线局域网802.11家族.网络中所有结点的地位平等,无需设置任何的中心控制结点,省去了无线中介设备AP.比如一台电脑建立了一个网络,这个时候加入了两台电脑. ...
- c# 串行化事件
- IP地址简介及Linux网络管理工具
IP地址简介 IP地址又叫网络地址也称逻辑地址,由32位2进制数组成,分4段每段8位,由10进制数表示,范围0~,段与段之间用点隔开采用点分十进制的表示法,在一个网络中ip地址是唯一的,IP地址最主要 ...
- Codeforces 750 E New Year and Old Subsequence
E. New Year and Old Subsequence 思路:线段树维护矩阵乘法. 代码: #pragma GCC optimize(2) #pragma GCC optimize(3) #p ...
- 在vue中使用css预编辑器
vue中使用less 安装less依赖,npm install less less-loader --save vue中使用sass npm install --save-dev sass-loade ...
- python开发的百度翻译接口
做的一个python版的百度翻译,附代码 #!/usr/bin/env python # -*- coding:utf-8 -*- ''' 爬虫之百度翻译 需要的库有 js2py, request ...
- archlinux 蓝牙耳机没有声音
前提 蓝牙已开,并且连接成功,但是蓝牙耳机没有声音. 安装 pacman -S pulseaudio-bluetooth pulsemixer 切换设备输出为蓝牙耳机
- css、js文件后的后缀作用是什么?
文章转自:https://blog.csdn.net/yelbosh/article/details/47303247 <link rel="stylesheet" type ...