【1】网络属性

man getsockopt
man 3 getsockopt
更新man手册
sudo apt-get install manpages-de  manpages-de-dev  manpages-dev glibc-doc manpages-posix-dev manpages-posix
功能:获取和设置网络属性;
头文件:#include <sys/types.h>          /* See NOTES */#include <sys/socket.h>
原型:int getsockopt(int sockfd, int level, int optname, void *optval, socklen_t *optlen);int setsockopt(int sockfd, int level, int optname,  const void *optval, socklen_t optlen);int a = 1;setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &a, sizeof(a));参数:int sockfd:指定要设置/获取属性的套接字;int level:指定要控制套接字的层次;SOL_SOCKET  应用层,通用套接字选项;            man 7 socketIPPROTO_TCP: TCP选项                       man 7 tcpIPPROTO_UDP: UDP选项;                      man 7 udpIPPROTO_IP:  IP选项;                       man 7 ipint optname:指定控制方式;以下以 SOL_SOCEKT为例:man 7 socketSO_REUSEADDR:允许端口快速重用SO_RCVBUF:接收缓冲区大小;SO_SNDBUF:发送缓冲区大小;SO_BROADCAST:广播;void *optval:根据optname的不同,数据类型不同;socklen_t* optlen:optval指向的变量的大小;
返回值:成功,返回0;失败,返回-1,更新errno;

【2】多点通讯

1. 单播

  1. 注意之间一对一的通信,交换机和路由器对数据只做转发不做复制;

  2. 每次只有两个实体相互通讯,发送端和接收端都是唯一确定的。

2. 广播

1)概念

  1. 主机之间一对多的通信方式,网络对其中每一台主机发出的信息都进行无条件复制并转发;

  2. 所有主机都可以接收到所有信息,无论你是否需要,由于其不用路径选择,所以其网络成本比较低;

  3. 禁止广播数据穿过路由器,防止广播数据造成大面积影响

  4. 只有UDP才能广播

  5. 广播的地址:主机号全是1

    192.168.1.41那么他的广播地址192.168.1.255;

    255.255.255.255 给所有网段中的所有主机发送广播,但是由于广播数据不能穿过路由器,所以实际上是给当前局域网下的主机发送;

2)广播的发送端流程(类似客户端)

  1. 创建报式套接字 (socket)

  2. 可选择绑定也可以不绑定地址信息结构体 (bind)

  3. 设置网络属性:允许广播,如果不设置,默认是不允许的(setsockopt)

  4. 填充广播的地址信息结构体:端口号 IP地址(广播IP 例如192.168.1.255 255.255.255.255)

  5. 发送数据 (sendto)

3)广播的接收端流程(类似服务器)

  1. 创建报式套接字 (socket)

  2. 必须绑定地址信息结构体:绑定广播IP地址(192.168.1.255 或者 0.0.0.0)和 端口号 (bind)

    注意:绑定的端口号必须和发送端填充的端口号一致;

  3. 等待接收数据(recvfrom)

4)发送方代码

#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <string.h>
#include <unistd.h>
​
​
#define ERR_MSG(msg) do{\fprintf(stderr, "__%d__ :", __LINE__);\perror(msg);\
}while(0)
​
#define PORT 2222
#define IP  "192.168.1.255"     //255.255.255.255
​
#define N 128
​
int main(int argc, const char *argv[])
{//创建报式套接字int sfd = socket(AF_INET, SOCK_DGRAM, 0);if(sfd < 0){ERR_MSG("socket");return -1;}
​//允许广播int broad = 1;if(setsockopt(sfd, SOL_SOCKET, SO_BROADCAST, &broad, sizeof(broad))<0){ERR_MSG("setsockopt");return -1;}
​//填充地址服务器信息结构体struct sockaddr_in sin;sin.sin_family      = AF_INET;sin.sin_port        = htons(PORT);sin.sin_addr.s_addr = inet_addr(IP);
​char buf[N] = "";while(1){bzero(buf, sizeof(buf));
​printf("请输入>>>");fgets(buf, sizeof(buf), stdin);buf[strlen(buf)-1] = 0;
​//将数据发送到服务器if(sendto(sfd, buf, sizeof(buf), 0, (struct sockaddr*)&sin, sizeof(sin))<0){ERR_MSG("sendto");return -1;}printf("发送成功\n");}
​close(sfd);return 0;
}

5)接收方代码

#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <string.h>
#include <unistd.h>
​
​
#define ERR_MSG(msg) do{\fprintf(stderr, "__%d__ :", __LINE__);\perror(msg);\
}while(0)
​
#define PORT 2222
#define IP  "192.168.1.255"     //0.0.0.0
​
#define N 128
​
int main(int argc, const char *argv[])
{//创建报式套接字int sfd = socket(AF_INET, SOCK_DGRAM, 0);if(sfd < 0){ERR_MSG("socket");return -1;}
​//允许端口快速重用int reuse = 1;if(setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse))<0){ERR_MSG("setsockopt");return -1;}
​//填充地址信息结构体struct sockaddr_in sin;sin.sin_family      = AF_INET;sin.sin_port        = htons(PORT);sin.sin_addr.s_addr = inet_addr(IP);
​//绑定地址信息if(bind(sfd, (struct sockaddr*)&sin, sizeof(sin))<0){ERR_MSG("bind");return -1;}printf("bind success\n");
​char buf[N] = "";struct sockaddr_in cin;socklen_t addrlen = sizeof(cin);while(1){//接收bzero(buf, sizeof(buf));if(recvfrom(sfd, buf, sizeof(buf), 0, (struct sockaddr*)&cin, &addrlen ) < 0){ERR_MSG("recvfrom");return -1;}
​printf("[%s:%d] %s\n", inet_ntoa(cin.sin_addr), ntohs(cin.sin_port), buf);}
​close(sfd);return 0;
}

3. 组播

1)概念

  1. 广播方式是发送给同一网段下的所有主机,过多的广播会占用大量网络带宽,会造成广播风暴,影响正常通讯;

  2. 主机之间一对一组的通讯模式,也就是只有加入了同一个组的主机可以接收到此组内的所有数据;

  3. 网络中的交换机和路由器只向需求者复制并转发数据;

  4. 组播IP地址: D类IP地址: 224.0.0.0~239.255.255.255

2)组播的发送端流程(类似客户端)

  1. 创建报式套接字 (socket)

  2. 可选择绑定也可以不绑定地址信息结构体 (bind)

  3. 填充接收方的IP地址及端口:IP地址:组播IP地址(224.0.0.0~239.255.255.255)

  4. 发送数据(sendto)

3)组播的接收端流程 (类似服务器)

  1. 创建报式套接字 (socket)

  2. 加入多播组 (setsockopt)

  3. 必须绑定地址信息结构体:IP地址:绑定组播IP地址(例如:224.1.2.3 或者 0.0.0.0)和端口 (bind)

    注意:绑定的组播IP和端口号必须与发送方填充的一致;

  4. 等待接收数据(recvfrom)

4)如何加入多播组

功能:获取和设置网络属性;
头文件:#include <sys/types.h>          /* See NOTES */#include <sys/socket.h>
原型:int setsockopt(int sockfd, int level, int optname,  const void *optval, socklen_t optlen);参数:int sockfd:指定要设置属性的套接字;int level:指定要控制套接字的层次;IPPROTO_IP:  IP选项;                       man 7 ipint optname:指定控制方式;IP_ADD_MEMBERSHIPvoid *optval:根据optname的不同,数据类型不同;struct ip_mreqn {struct in_addr imr_multiaddr; //组播Ip地址的网络字节序struct in_addr imr_address;   //本机IP地址的网络字节序int            imr_ifindex;   //当前使用的网络设备索引号/*1.ifconfig 找到网卡名 例如:"ens33".ip ad 找到"ens33"对应的索引号,例如:22.通过函数的方式查找if_nametoindex(网卡的名字);  例如:if_nametoindex("ens33");3.填0,默认索引号*/};
​socklen_t optlen:optval指向的变量的大小;
返回值:成功,返回0;失败,返回-1,更新errno;            

5)发送端代码

#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <string.h>
#include <unistd.h>
​
​
#define ERR_MSG(msg) do{\fprintf(stderr, "__%d__ :", __LINE__);\perror(msg);\
}while(0)
​
#define PORT 2222
#define IP  "224.1.2.3"     //224.0.0.0~239.255.255.255
​
#define N 128
​
int main(int argc, const char *argv[])
{//创建报式套接字int sfd = socket(AF_INET, SOCK_DGRAM, 0);if(sfd < 0){ERR_MSG("socket");return -1;}
​
​//填充地址接收方地址信息结构体struct sockaddr_in sin;sin.sin_family      = AF_INET;sin.sin_port        = htons(PORT);sin.sin_addr.s_addr = inet_addr(IP);
​char buf[N] = "";int i = 0;while(1){/*sprintf(buf, "hello %d", i);i++;*/bzero(buf, sizeof(buf));
​printf("请输入>>>");fgets(buf, sizeof(buf), stdin);buf[strlen(buf)-1] = 0;
​//将数据发送到服务器if(sendto(sfd, buf, sizeof(buf), 0, (struct sockaddr*)&sin, sizeof(sin))<0){ERR_MSG("sendto");return -1;}printf("发送成功\n");}
​close(sfd);return 0;
}

6)接收端代码

#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <string.h>
#include <unistd.h>
#include <net/if.h>
​
​
#define ERR_MSG(msg) do{\fprintf(stderr, "__%d__ :", __LINE__);\perror(msg);\
}while(0)
​
#define PORT 2222
#define GROUP_IP    "224.1.2.3" //224.0.0.0~239.255.255.255 与发送放一致
​
#define N 128
​
int main(int argc, const char *argv[])
{//创建报式套接字int sfd = socket(AF_INET, SOCK_DGRAM, 0);if(sfd < 0){ERR_MSG("socket");return -1;}
​//允许端口快速重用int reuse = 1;if(setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse))<0){ERR_MSG("setsockopt");return -1;}
​//加入多播组struct ip_mreqn mq;mq.imr_multiaddr.s_addr = inet_addr(GROUP_IP);  //组播Ip地址mq.imr_address.s_addr = inet_addr("192.168.1.12");  //本机IP地址mq.imr_ifindex = if_nametoindex("ens33");   //网络设备索引号
​if(setsockopt(sfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mq, sizeof(mq)) < 0){ERR_MSG("setsockopt");return -1;}
​//填充地址信息结构体struct sockaddr_in sin;sin.sin_family      = AF_INET;sin.sin_port        = htons(PORT);sin.sin_addr.s_addr = inet_addr(GROUP_IP);  //组播地址
​//绑定地址信息if(bind(sfd, (struct sockaddr*)&sin, sizeof(sin))<0){ERR_MSG("bind");return -1;}printf("bind success\n");
​char buf[N] = "";struct sockaddr_in cin;socklen_t addrlen = sizeof(cin);while(1){//接收bzero(buf, sizeof(buf));if(recvfrom(sfd, buf, sizeof(buf), 0, (struct sockaddr*)&cin, &addrlen ) < 0){ERR_MSG("recvfrom");return -1;}
​printf("[%s:%d] %s\n", inet_ntoa(cin.sin_addr), ntohs(cin.sin_port), buf);}
​close(sfd);return 0;
}

【3】项目:基于UDP的网络聊天室

1. 需求

项目需求:

  1. 如果有用户登录,其他用户可以收到这个人的登录信息

  2. 如果有人发送信息,其他用户可以收到这个人的群聊信息

  3. 如果有人下线,其他用户可以收到这个人的下线信息

  4. 服务器可以发送系统信息

写项目的方法:

  1. 画流程图

  2. 根据流程图写框架

  3. 将每个功能实现(一个一个实现,不要一起写)

2. 流程图

 3.项目代码

GitHub - xuyongxiang/ChatRoom: 基于UDP的网络聊天室

网络编程之UDP多点通讯相关推荐

  1. Python中的网络编程之UDP

    Python中的网络编程之UDP 文章目录 Python中的网络编程之UDP 一.Socket编程 `1.什么是客户端/服务器架构`? **`2.套接字:通信端点`** 3.套接字地址:主机-端口对 ...

  2. 萌新解--Java网络编程之UDP

    Java网络编程之UDP UDP协议为无连接的通信协议,在传数据前发送端与接收端不会先建立连接,也就是你发我就收但不一定会收到哦,以我们自身为发送端,我们不会事先让接收方知道我要给接收方发数据啦.就像 ...

  3. 1.6 网络编程之 UDP通信

    ************************************************** * 本文由小鸟飞飞整理发表 <samboy@sohu.com> * * 首发网站:蓝丽 ...

  4. Java网络编程之UDP和TCP套接字

    文章目录 一. 网络编程概述 二. UDP网络编程 1. UDP套接字 2. UDP客户端回显服务器程序 2.1 UDP回显服务器 2.2 UDP客户端 2.3 UDP实现查词典的服务器 三. TCP ...

  5. java网络编程udp_Java网络编程之UDP

    UDP是User Datagram Protocol的简称,中文名是用户数据报协议,是OSI(Open System Interconnection,开放式系统互联)参考模型中一种无连接的传输层协议, ...

  6. java udp 同一个端口实现收发_Java网络编程之UDP协议

    伙伴们注意了! 小编在这里给大家送上关注福利: 搜索微信公众号"速学Java"关注即可领取小编精心准备的资料一份! 今天我们来聊聊 网络编程这部分的内容 网络编程 1)计算机网络 ...

  7. Linux C高级编程——网络编程之UDP(4)

    Linux网络编程--UDP 宗旨:技术的学习是有限的,分享的精神是无限的. 下面分析一帧基于UDP的TFTP协议帧. 以太网首部 0000: 00 05 5d 67 d0 b1 00 05 5d 6 ...

  8. python udp创建addr_一篇文章搞定Python 网络编程之UDP协议

    基于UDP协议的socket PS:udp是无连接的,先启动那一端都不会报错 server端 import socket # 导入socket模块udp_sk = socket.socket(type ...

  9. C#网络编程之 UDP编程

    C# 网络编程 UDP 转载于:https://www.cnblogs.com/miniwiki/archive/2009/07/24/1709833.html

最新文章

  1. python---简单数据库
  2. Kimera:一个基于度量语义的SLAM开源库
  3. Linux的ELF格式分析
  4. SAP Customer Data Cloud(Gigya)的用户搜索实现
  5. 认证授权方案之授权揭秘 (上篇)
  6. 实验2 java_《Java程序设计》实验2
  7. 他让全世界凶手睡不着觉,现实版福尔摩斯,退休了4次又被拽回来工作,无敌实在是太寂寞了~...
  8. Servlet读取文件的最好的方式
  9. Impala:大数据丛林中敏捷迅速的黑斑羚
  10. 大家不要催!雷军的螺丝刀已经准备好了...
  11. 雷赛控制卡系统集成源代码。整理归零,运行,暂停,停止。单轴调 试,位置移动,气缸操作,参数设置,IO监控,系统报警显示等等
  12. c语言 拟合指数函数的代码,如何找到拟合指数函数的x?
  13. Technorati.com 被劫持
  14. Stripe 自动分账
  15. 服务器站点地址是什么意思,云服务器地址是什么意思
  16. ***虚拟专用网技术
  17. 讲一点点自动驾驶技术(1)概论
  18. soso地图api接口poi检索示例----并在信息框显示经纬度
  19. 7-1 sdut-求一个3*3矩阵对角线元素之和7-2 求矩阵各行元素之和7-3 sdut- 对称矩阵的判定7-4 sdut- 杨辉三角7-5 sdut- 鞍点计算7-6 矩阵转置
  20. 一个BUG(缺陷)的生命周期

热门文章

  1. 中专计算机专业具体学习内容是什么?
  2. 【物联网】17.物联网传感器信号处理 - 信号放大电路
  3. 论文阅读笔记:Glyce: Glyph-vectors for Chinese Character Representations
  4. matlab 开环系统 求相位裕度,用MATLAB进行控制系统的..
  5. Spring拦截器HandlerInterceptor和HandlerInterceptorAdapter
  6. 【保研之路】北邮人工智能、天大计算机、中国科学技术大学
  7. QoS的流分类与标记
  8. Matlab 两种比较三个数的大小
  9. 瑞典军事研究:从认知心理学的视角探讨军事创新进程
  10. Java 100-002:Swing显示窗口,并在窗口中显示文字