udp通信(udp通信和tcp通信区别)
UDP和Socket通信步骤是什么?
UDP Server程序\x0d\x0a1、编写UDP Server程序的步骤\x0d\x0a(1)使用socket()来建立一个UDP socket,第二个参数为SOCK_DGRAM。\x0d\x0a(2)初始化sockaddr_in结构的变量,并赋值。sockaddr_in结构定义:\x0d\x0astruct sockaddr_in {\x0d\x0auint8_t sin_len;\x0d\x0asa_family_t sin_family;\x0d\x0ain_port_t sin_port;\x0d\x0astruct in_addr sin_addr;\x0d\x0achar sin_zero[8];\x0d\x0a};\x0d\x0a这里使用“08”作为服务程序的端口,使用“INADDR_ANY”作为绑定的IP地址即任何主机上的地址。\x0d\x0a(3)使用bind()把上面的socket和定义的IP地址和端口绑定。这里检查bind()是否执行成功,如果有错误就退出。这样可以防止服务程序重复运行的问题。\x0d\x0a(4)进入无限循环程序,使用recvfrom()进入等待状态,直到接收到客户程序发送的数据,就处理收到的数据,并向客户程序发送反馈。这里是直接把收到的数据发回给客户程序。\x0d\x0a\x0d\x0a2、udpserv.c程序内容:\x0d\x0a#include \x0d\x0a#include \x0d\x0a#include \x0d\x0a#include \x0d\x0a#include \x0d\x0a#include \x0d\x0a\x0d\x0a#define MAXLINE 80\x0d\x0a#define SERV_PORT 8888\x0d\x0a\x0d\x0avoid do_echo(int sockfd, struct sockaddr *pcliaddr, socklen_t clilen)\x0d\x0a{\x0d\x0aint n;\x0d\x0asocklen_t len;\x0d\x0achar mesg[MAXLINE];\x0d\x0a\x0d\x0afor(;;)\x0d\x0a{\x0d\x0alen = clilen;\x0d\x0a/* waiting for receive data */\x0d\x0an = recvfrom(sockfd, mesg, MAXLINE, 0, pcliaddr, len);\x0d\x0a/* sent data back to client */\x0d\x0asendto(sockfd, mesg, n, 0, pcliaddr, len);\x0d\x0a}\x0d\x0a}\x0d\x0a\x0d\x0aint main(void)\x0d\x0a{\x0d\x0aint sockfd;\x0d\x0astruct sockaddr_in servaddr, cliaddr;\x0d\x0a\x0d\x0asockfd = socket(AF_INET, SOCK_DGRAM, 0); /* create a socket */\x0d\x0a\x0d\x0a/* init servaddr */\x0d\x0abzero(servaddr, sizeof(servaddr));\x0d\x0aservaddr.sin_family = AF_INET;\x0d\x0aservaddr.sin_addr.s_addr = htonl(INADDR_ANY);\x0d\x0aservaddr.sin_port = htons(SERV_PORT);\x0d\x0a\x0d\x0a/* bind address and port to socket */\x0d\x0aif(bind(sockfd, (struct sockaddr *)servaddr, sizeof(servaddr)) == -1)\x0d\x0a{\x0d\x0aperror("bind error");\x0d\x0aexit(1);\x0d\x0a}\x0d\x0a\x0d\x0ado_echo(sockfd, (struct sockaddr *)cliaddr, sizeof(cliaddr));\x0d\x0a\x0d\x0areturn 0;\x0d\x0a}\x0d\x0a\x0d\x0aUDP Client程序\x0d\x0a1、编写UDP Client程序的步骤\x0d\x0a(1)初始化sockaddr_in结构的变量,并赋值。这里使用“8888”作为连接的服务程序的端口,从命令行参数读取IP地址,并且判断IP地址是否符合要求。\x0d\x0a(2)使用socket()来建立一个UDP socket,第二个参数为SOCK_DGRAM。\x0d\x0a(3)使用connect()来建立与服务程序的连接。与TCP协议不同,UDP的connect()并没有与服务程序三次握手。上面我们说了UDP是非连接的,实际上也可以是连接的。使用连接的UDP,kernel可以直接返回错误信息给用户程序,从而避免由于没有接收到数据而导致调用recvfrom()一直等待下去,看上去好像客户程序没有反应一样。\x0d\x0a(4)向服务程序发送数据,因为使用连接的UDP,所以使用write()来替代sendto()。这里的数据直接从标准输入读取用户输入。\x0d\x0a(5)接收服务程序发回的数据,同样使用read()来替代recvfrom()。\x0d\x0a(6)处理接收到的数据,这里是直接输出到标准输出上。\x0d\x0a\x0d\x0a2、udpclient.c程序内容:\x0d\x0a#include \x0d\x0a#include \x0d\x0a#include \x0d\x0a#include \x0d\x0a#include \x0d\x0a#include \x0d\x0a#include \x0d\x0a#include \x0d\x0a\x0d\x0a#define MAXLINE 80\x0d\x0a#define SERV_PORT 8888\x0d\x0a\x0d\x0avoid do_cli(FILE *fp, int sockfd, struct sockaddr *pservaddr, socklen_t servlen)\x0d\x0a{\x0d\x0aint n;\x0d\x0achar sendline[MAXLINE], recvline[MAXLINE + 1];\x0d\x0a\x0d\x0a/* connect to server */\x0d\x0aif(connect(sockfd, (struct sockaddr *)pservaddr, servlen) == -1)\x0d\x0a{\x0d\x0aperror("connect error");\x0d\x0aexit(1);\x0d\x0a}\x0d\x0a\x0d\x0awhile(fgets(sendline, MAXLINE, fp) != NULL)\x0d\x0a{\x0d\x0a/* read a line and send to server */\x0d\x0awrite(sockfd, sendline, strlen(sendline));\x0d\x0a/* receive data from server */\x0d\x0an = read(sockfd, recvline, MAXLINE);\x0d\x0aif(n == -1)\x0d\x0a{\x0d\x0aperror("read error");\x0d\x0aexit(1);\x0d\x0a}\x0d\x0arecvline[n] = 0; /* terminate string */\x0d\x0afputs(recvline, stdout);\x0d\x0a}\x0d\x0a}\x0d\x0a\x0d\x0aint main(int argc, char **argv)\x0d\x0a{\x0d\x0aint sockfd;\x0d\x0astruct sockaddr_in srvaddr;\x0d\x0a\x0d\x0a/* check args */\x0d\x0aif(argc != 2)\x0d\x0a{\x0d\x0aprintf("usage: udpclient \n");\x0d\x0aexit(1);\x0d\x0a}\x0d\x0a\x0d\x0a/* init servaddr */\x0d\x0abzero(servaddr, sizeof(servaddr));\x0d\x0aservaddr.sin_family = AF_INET;\x0d\x0aservaddr.sin_port = htons(SERV_PORT);\x0d\x0aif(inet_pton(AF_INET, argv[1], servaddr.sin_addr)
回答于?2022-11-17
Socket 通信之 UDP 通信
前段时间,我们在 这篇文章 中谈到了多进程和进程之间的通信方式,主要谈到了本地进程之间使用队列(Queue)进程通信,如果我们要通信的进程不在同一台主机上,我们就无法使用队列进行通信了,这时就需要使用 Socket(套接字)。
Socket 是应用层和传输层之间的一层抽象协议,可以用来进行进程间通信,一般有 UDP 和 TCP 两种通信方式,前者速度稍快,稳定性不好,无法丢包重传。后者速度稍慢一点,但稳定性很好,可以丢包重传。
本文首先介绍使用 Socket 进行 UDP 通信。
使用 Socket 进行 UDP 通信的流程如下:
下面依次进行讲解。
要进行 Socket 通信,我们需要使用 socket 模块,首先需要创建一个 Socket 对象。下面是两种创建方式:
如果我们需要向别的主机发送数据,我们需要改主机的 IP 地址和相应的端口号。在使用 Socket 进行通信时,需要将两个信息写在一元组中,元组的第一项为目标主机 IP 地址,第二项为接受数据的端口号:
其中,IP 地址使用字符串类型,端口号使用数字类型。
如果不绑定端口,每次使用 Socket 时都会由操作系统动态分配一个端口,我们也可以绑定为某个固定的端口。这样做的好处是:如果我们想要接受其他主机的信息,其他主机可以直接向这个端口发送数据,如果使用动态端口的话,发送方并不知道目标端口是什么,因此无法向接收方发送数据。
绑定端口需要使用 Socket 对象的 bind 方法:
bind 方法接受一个元组作为参数,元组的第一项为绑定的 IP 地址,第二项为绑定的端口号。我们可以把第一项指定为本机上的任意一个 IP 地址,也可以设置为一个空字符串 "" ,表示本机上任意合法的 IP 地址。
使用 UDP 套接字协议时,发送数据使用 Socket 对象的 sendto 方法,接受数据使用 Socket 对象的 recvfrom 方法。这两个方法的使用方式如下:
sendto 方法接受两个参数:发送的数据和目标主机的 IP 和端口元组,在 Python3 中,发送的数据应该转为 byte 类型发送,Python2 中可以直接发送字符串。
recvfrom 接受一个参数:本次接受的最大数据尺寸。该方法是阻塞的,只有在接收到数据后才能进行后续的操作。
就像使用文件那样,在使用完套接字后,需要关闭它,调用 close 方法即可。
上面我们介绍了 Socket 的使用方式,下面我们来做一个单工通信的例子(一方负责发送信息,一方负责接收信息)。
我们这里来创建两个文件:用以发送信息的 send.py 和用以接收信息的 recv.py。该实例在虚拟机中模拟(注意将虚拟机设置为桥接模式)。
创建 send.py:
创建 recv.py:
运行结果如下:
上面实现了一个单工通信的例子:一方负责发,一方负责接收。下面我们继续实现一个双工通信的例子,使双方都能够收发消息。
由于接收和发送消息时是使用 while 循环不断轮询的,因此要实现同时发送和接受,我们需要进行多任务处理。
新建一个 msg.py:
这里我们使用 3000 端口发送数据,3001 端口接收数据,运行程序时只需填写目标主机的 IP 地址,就可以进行通信。
运行效果:
我们还可以进行局域网内的广播,只需对 Socket 加上一条设置:
同时,发送广播需要一个广播地址,以及目标主机接受广播的端口:
上面的设置只能给 0 网段的主机发送广播,要想给局域网中所有的主机发送广播,可以这样设置:
下面我们新建一个 send.py 用来发送广播:
新建一个 recv.py 用来接收广播:
运行效果如图:
完。
UDP是什么意思?
UDP 是User Datagram Protocol的简称, 中文名是用户数据报协议,是OSI(Open System Interconnection,开放式系统互联) 参考模型中一种无连接的传输层协议,提供面向事务的简单不可靠信息传送服务,IETF RFC 768是UDP的正式规范。UDP在IP报文的协议号是17。
UDP 用户数据报协议,是一个无连接的简单的面向数据报的运输层协议。UDP不提供可靠性,它只是把应用程序传给IP层的数据报发送出去,但是并不能保证它们能到达目的地。由于UDP在传输数据报前不用在客户和服务器之间建立一个连接,且没有超时重发等机制,故而传输速度很快。
UDP是一种面向无连接的协议,每个数据报都是一个独立的信息,包括完整的源地址或目的地址,它在网络上以任何可能的路径传往目的地,因此能否到达目的地,到达目的地的时间以及内容的正确性都是不能被保证的。
扩展资料:
UDP是面向无连接的通讯协议,UDP数据包括目的端口号和源端口号信息,由于通讯不需要连接,所以可以实现广播发送。
UDP传输数据时有大小限制,每个被传输的数据报必须限定在64KB之内。 UDP是一个不可靠的协议,发送方所发送的数据报并不一定以相同的次序到达接收方。
UDP是面向消息的协议,通信时不需要建立连接,数据的传输自然是不可靠的,UDP一般用于多点通信和实时的数据业务。
参考资料:百度百科-UDP
网线UDP通信(ubuntu设置静态ip)
c++的udp socket,收端要绑定端口号(具体见dell笔记本的sever.cpp)
python的udp scoket,收端要bind自己的ip和port
sudo nano /etc/dhcpcd.conf进入树莓派设置
一、使用命令设置Ubuntu IP地址
1.修改配置文件blacklist.conf禁用IPV6
表示用vi编辑器(也可以用其他编辑器,如gedit)编辑etc文件夹下modprobe.d文件夹中blacklist.conf文档的内容。
注意:只能在root用户模式下才可以修改
在文档最后添加 blacklist ipv6
然后查看修改结果
2.设置网卡eth0的IP地址和子网掩码
将IP地址改为:192.168.2.1,子网掩码改为:255.255.255.0
3.Ubuntu IP设置网关
4.Ubuntu IP设置DNS 修改/etc/resolv.conf,在其中加入nameserver DNS的地址1 和 nameserver DNS的地址2 完成。
5.重启网络服务(若不行,请重启ubuntu:sudo reboot)
6.查看当前IP
二、直接修改Ubuntu IP系统配置文件
Ubuntu IP的网络配置文件是根目录下:/etc/network/interfaces
注意:修改完interfaces文档中的内容后,需要修改/etc/NetworkManager/NetworkManager.conf文档中的managed参数,使之为true,并重启。否则,会提示说“有线网络设备未托管”。
打开后里面可设置DHCP或手动设置静态IP。
前面auto eth0,表示让网卡开机自动挂载eth0。
1. 以DHCP方式配置网卡
编辑文件 /etc/network/interfaces
并用下面的行来替换有关eth0的行:
#The primary network interface - use DHCP to find our address
用下面的命令使网络设置生效:
也可以在命令行下直接输入下面的命令来获取地址sudo dhclient eth0
2. 为网卡配置静态Ubuntu IP地址
编辑文件 /etc/network/interfaces
并用下面的行来替换有关eth0的行:
将eth0的IP分配方式修改为静态分配(static)后,为其制定IP、网关、子网掩码等信息。
将上面的Ubuntu IP地址等信息换成你自己就可以了。
用下面的命令使网络设置生效:
示例:
注意:
若/etc/init.d/networking restart 重启无效,可以直接采用
3. 设定第二个Ubuntu IP地址(虚拟IP地址)
编辑文件/etc/network/interfaces:?
在该文件中添加如下的行:
根据你的情况填上所有诸如address,netmask,network,broadcast和gateways等信息;
用下面的命令使网络设置生效
4. 设置主机名称(hostname)
使用下面的命令来查看当前主机的主机名称:sudo /bin/hostname
使用下面的命令来设置当前主机的主机名称:sudo /bin/hostname newname
系统启动时,它会从/bin/hostname来读取主机的名称。
5. 配置DNS
首先,你可以在/etc/hosts中加入一些主机名称和这些主机名称对应的IP地址,这是 简单使用本机的静态查询。要访问DNS 服务器来进行查询,需要设置/etc/resolv.conf文件,假设DNS服务器的IP地址是192.168.2.2, 那么/etc/resolv.conf文件的内容应为:
search chotim.com
nameserver 192.168.2.2
6.手动重启网络服务:sudo /etc/init.d/networking restart
返回结果如下:
*Reconfiguring network interfaces… [OK]
————————————————
原文链接: