网络与通信程序设计-基于UDP的广播通信实例
目录
实验内容和设计思想
实验的内容
UDP的设计思想
UDP的协议头部
UDP通信编程思想
UDP的工作流程
UDP编程收发函数
广播通信
广播模式设置
广播套接字
UDP 的使用过程
UDP广播通信实例实现
.h
服务器发送广播消息
客户端接收广播消息
运行效果
实验心得
实验内容和设计思想
通过本文的学习,希望可以帮助大家完成一个简易的基于UDP的广播通信实例
实验的内容
编写基于广播通信模型的服务器端和客户端通信程序,要求编程实现服务器端与客户端之间广播数据传递。服务器端向所有客户端发送“今天是个好日子!”广播消息,客户端收到并在本地显示给用户。
UDP的设计思想
由于UDP协议本身异常简单,实际上只为IP传输起到了桥梁的作用,在一些场景上通过【 应用层->UDP->IP 】的封装方式,可以极大的提高程序调用效率。
UDP(User )传输与IP传输非常类似。你可以将UDP协议看作IP协议暴露在传输层的一个接口。UDP协议同样以数据包()的方式传输,它的传输方式也是"Best "的,所以UDP协议也是不可靠的()。
UDP是一个无连接协议,传输数据之前源端和终端不建立连接,当它想传送时就简单地去抓取来自应用程序的数据,并尽可能快地把它扔到网络上。在发送端,UDP传送数据的速度仅仅是受应用程序生成数据的速度、计算机的能力和传输带宽的限制;在接收端,UDP把每个消息段放在队列中,应用程序每次从队列中读一个消息段。
由于传输数据不建立连接,因此也就不需要维护连接状态,包括收发状态等,因此一台服务机可同时向多个客户机传输相同的消息。
UDP的协议头部
port
出发端口
port
目的地端口
UDP包的长度
IP协议的 算法相类似
UDP通信编程思想 UDP的工作流程
UDP 用户数据报协议提供的是无连接的、不可靠的数据传输服务,但是不需要像 TCP 那样建立连接,所以传输效率高。
对比TCP的工作流程
UDP编程收发函数
UDP编程的数据收发函数为()和()
int sendto(SOCKET s, //发送数据的套接字const char FAR * buf, //发送数据的缓冲区int len, //发送数据的长度int flags, //一般指定为0const struct sockaddr FAR * to, //指向一个包含目标地址和端口号的sockaddr_in结构int tolen //为sockaddr_in结构的大小);
同样的接收数据的函数是 (),UDP接收数据时也需要知道通信对端的地址信息。
int recvfrom(SOCKET s,char FAR*buf,int len,int flag,struct sockaddr_in FAR*from,int FAR*fromlen)
广播通信
利用广播()可以将数据发送给本地子网上的每个机器,同时需要有一些线程在机器上监听到来的数据。广播的缺点是如果多个进程都发送广播数据,网络就会阻塞,网络性能便会受到影响。
利用广播()可以将数据发送给本地子网上的每个机器。
广播模式设置 广播套接字
获取和设置套接字选项的函数分别是 ()和 (),函数调用出错时返回 ERROR。
int setsockopt(SOCKET s,int level,int optname,const char FAR * optval,int* optlen);
参数说明:
同理接收套接字也采用类似于的定义模式
int getsockopt(SOCKET s,int level, optname, const char FAR * optval,int* optlen);
此外,进行广播通信,必须打开广播选项为True。
选项设置套接字传输和接收广播消息,如果给定套接字已经被设置为接收或者发送广播数据,查询此套接字选项将返回TRUE,此选项对于那些不是类型的套接字有效。
SOCKET s = ::socket(AF_INET, SOCK_DGRAM, 0);// 有效SO_BROADCAST选项BOOL bBroadcast = TRUE;::setsockopt(s, SOL_SOCKET, SO_BROADCAST, (char*)&bBroadcast, sizeof(BOOL));
UDP 的使用过程
1. 初始化网络库
2. 创建类型的。
3. 绑定套接字。
4. 发送、接收数据。
5. 销毁套接字。
6. 释放网络库。
UDP广播通信实例实现
实现服务器端与客户端之间广播数据传递,服务器端向所有客户端发送“今天是个好日子!”广播消息,客户端收到并在本地显示。
.h
#include
#pragma comment(lib, "WS2_32") // 链接到 WS2_32.libclass CInitSock
{
public:/*CInitSock 的构造器*/CInitSock(BYTE minorVer = 2, BYTE majorVer = 2){// 初始化WS2_32.dllWSADATA wsaData;WORD sockVersion = MAKEWORD(minorVer, majorVer);if (::WSAStartup(sockVersion, &wsaData) != 0){exit(0);}}/*CInitSock 的析构器*/~CInitSock(){::WSACleanup();}
};
服务器发送广播消息
对于 UDP 来说存在一个特定的广播地址 255.255.255.255,广播数据都应该发送到这里。发送方程序在创建套接字后使用 函数打开 选项,然后设置广播地址 255.255.255.255,使用 函数向端口号 54321 不断发送广播数据。
#include "initsock.h"
#include
#include
using namespace std;CInitSock theSock;int main()
{SOCKET s = ::socket(AF_INET, SOCK_DGRAM, 0);// 有效SO_BROADCAST选项BOOL bBroadcast = TRUE;::setsockopt(s, SOL_SOCKET, SO_BROADCAST, (char*)&bBroadcast, sizeof(BOOL));// 设置广播地址和广播端口号SOCKADDR_IN bcast;bcast.sin_family = AF_INET;bcast.sin_port = htons(54321);bcast.sin_addr.s_addr = INADDR_BROADCAST;// 发送广播cout << " 开始向端口发送广播数据... \n" << endl;char sz[] = "今天是个好日子! \r\n";while (TRUE){time_t now = time(0); // 基于当前系统的当前日期/时间char* dt = ctime(&now);::sendto(s, sz, strlen(sz), 0, (sockaddr*)&bcast, sizeof(bcast));cout << dt << "发送广播:" << sz << endl;::Sleep(5000);}return 0;
}
客户端接收广播消息
使用 函数,向端口号 54321 接收广播数据。
#include "initsock.h"
#include
#include
using namespace std;CInitSock theSock;int main()
{SOCKET s = ::socket(AF_INET, SOCK_DGRAM, 0);// 首先要绑定一个本地地址,指明广播端口号SOCKADDR_IN sin;sin.sin_family = AF_INET;sin.sin_port = htons(54321);sin.sin_addr.S_un.S_addr = INADDR_ANY;if (::bind(s, (sockaddr*)&sin, sizeof(sin)) == SOCKET_ERROR){cout << " bind() failed!" << endl;return 0;}// 接收广播cout << " 开始在端口接收广播数据... \n" << endl;SOCKADDR_IN addrRemote;int nLen = sizeof(addrRemote);char sz[256];while (TRUE){int nRet = ::recvfrom(s, sz, 256, 0, (sockaddr*)&addrRemote, &nLen);if (nRet > 0){sz[nRet] = '\0';time_t now = time(0); // 基于当前系统的当前日期/时间char* dt = ctime(&now);cout << dt << "接收到广播:" << sz << endl;}}return 0;
}
运行效果
实验心得
1,为了进行广播通信,必须打开广播选项
2,接收方一定要知道广播方的端口号,然后绑定此端口号才能正确接收。
3,UDP(User )传输与IP传输非常类似。你可以将UDP协议看作IP协议暴露在传输层的一个接口。UDP协议同样以数据包()的方式传输,它的传输方式也是"Best "的,所以UDP协议也是不可靠的()。
4,由于UDP协议本身异常简单,实际上只为IP传输起到了桥梁的作用,在一些场景上通过应用层->UDP->IP的封装方式,可以极大的提高程序调用效率。
5,UDP是一个无连接协议,传输数据之前源端和终端不建立连接,当它想传送时就简单地去抓取来自应用程序的数据,并尽可能快地把它扔到网络上。在发送端,UDP传送数据的速度仅仅是受应用程序生成数据的速度、计算机的能力和传输带宽的限制;在接收端,UDP把每个消息段放在队列中,应用程序每次从队列中读一个消息段。
由于传输数据不建立连接,因此也就不需要维护连接状态,包括收发状态等,因此一台服务机可同时向多个客户机传输相同的消息。