一、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,广播和组播的更多相关文章

  1. linux网络编程之二-----多播(组播)编程

    多播编程实例 服务器端 下面是一个多播服务器的例子.多播服务器的程序设计很简单,建立一个数据包套接字,选定多播的IP地址和端口,直接向此多播地址发送数据就可以了.多播服务器的程序设计,不需要服务器加入 ...

  2. Linux网络编程(四)

    在linux网络编程[1-3]中,我们编写的网络程序仅仅是为了了解网络编程的基本步骤,实际应用当中的网络程序并不会用那样的.首先,如果服务器需要处理高并发访问,通常不会使用linux网络编程(三)中那 ...

  3. Linux网络编程:UDP Socket编程范例

    TCP协议提供的是一种可靠的,复杂的,面向连接的数据流(SOCK_STREAM)传输服务,它通过三段式握手过程建立连接.TCP有一种"重传确认"机制,即接收端收到数据后要发出一个肯 ...

  4. Linux 网络编程四(socket多线程升级版)

    //网络编程--客户端 #include <stdio.h> #include <stdlib.h> #include <string.h> #include &l ...

  5. python网络编程(UDP+广播)

    UDP广播案例,一端发送,多端接受: 发送端: # UDP广播案例 from socket import * from time import sleep # 设定目标地址 dest=('176.21 ...

  6. UDP广播,组播服务器

    广播 #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/ ...

  7. Linux网络编程:UDP实现可靠的文件传输

    我们知道,用TCP实现文件传输很简单.相对于TCP,因为UDP是面向无连接.不可靠的传输协议,所以我们需要考虑丢包和后发先至(包的顺序)的问题,所以我们想要实现UDP传输文件,则需要解决这两个问题.方 ...

  8. linux网络编程笔记——UDP

    目前这部分代码会出现阻塞问题,暂时尚未解决 #include "udp.h" #include <stdio.h> #include <string.h> ...

  9. Linux 网络编程(UDP)

    客户端代码 #include<stdio.h> #include<stdlib.h> #include<string.h> #include<sys/sock ...

随机推荐

  1. RabbitMQ的应用场景

    进入正题. 一.异步处理 场景:发送手机验证码,邮件 传统古老处理方式如下图 这个流程,全部在主线程完成,注册->入库->发送邮件->发送短信,由于都在主线程,所以要等待每一步完成才 ...

  2. 依赖: libcheese-gtk23 (>= 3.4.0)

    unity-control-center : 依赖: libcheese-gtk23 (>= 3.4.0) 但是它将不会被安装                         依赖: libch ...

  3. CentOS && Ubuntu 环境下 Docker 的安装配置

    CentOS 7 install Docker Docker 支持的 centos 版本:CentOS 6.5(64-bit)或更高的版本 使用 yum 安装 1)确保 yum 包更新到最新 [roo ...

  4. iOS - SceneKit 3D引擎初探

    最近到处搜集资料研究3D最后还是决定锁定OC框架,找到的学习资料随后慢慢整理 SceneKit 是一个OC 框架,开始之前,先熟悉一下SceneKit 的三维坐标系: 很清楚的看到,SceneKit ...

  5. 微信H5支付(基于Java实现微信H5支付)

    微信的H5支付区别与APP支付,主要在于预下单(返回的参数不一样),其它大体相同(基本没什么区别,区别在于有些人加密喜欢用MD5有些人喜欢用官方提供的加密方式加密,我用的是官方的),贴一下H5支付预下 ...

  6. JAVA笔记整理(二),下载安装JDK

    Windows平台 1.登录Oracle官方网站(http://www.oracle.com/index.html),找到下载 2.选择要下载的版本,点击JDK DOWNLOAD 3.下载文件,先勾选 ...

  7. java后端处理高并发

    一个登陆页面可能会被很多账户同时登陆或者注册,那么我们就好处理这些并发,否则降低程序的使用率,甚至程序奔溃,下面一段代码处理程序的高并发效果不错. /** *@author xiaoxie *@dat ...

  8. Linux VPS搭建蚂蚁笔记Leanote私有云笔记存储平台

    一.基础环境LNMP 安装nginx: yum install epel-release -y yum install nginx -y # 启动 nginx systemctl start ngin ...

  9. Dotnet站点多个路由对应同一个Action的总结

    需求:有些浏览器会屏蔽带有Ad字样的路径,此时需要创建多个路由指向同一个Action. 例如:原来 : http://lalalalalala.org:1506/api/advert/common   ...

  10. github看项目-浏览器插件

    浏览器插件,使用浏览器看github项目 原文:浏览 GitHub 太卡了?教你两招!