如何进行网络编程(代码利用UDP socket实现)

article/2025/4/28 6:29:08

目录

一、什么是网络编程?

二、那么在Java中能调用C语言的函数吗?

三、操作系统提供的socket API主要有两类(实际上不止两类)

1.流套接字(底层使用TCP协议)

TCP协议的特点:

2.数据报套接字(底层使用UDP协议)

UDP协议的特点:

UDP socket中有两个核心的类:

四、正常的客户端/服务器的通信流程:

五、服务器的代码:

六、客户端和服务器

七、客户端的代码:

总结


一、什么是网络编程?

通过代码来控制,让两个主机进程之间能够进行数据交互。

例如我用微信发送一条消息,这个消息通过我电脑上的QQ客户端进程,先发送给了腾讯的服务器(对应的服务器进程),再由腾讯的服务器进程把这个消息发给对方电脑的QQ进程。

操作系统把网络编程的一些相关操作(管理网卡)封装起来了,提供了一组API供程序员来调用。

进行网络编程的核心就是通过代码操作网卡这个硬件设备。

操作系统对于网卡进行了抽象,进程想去操作网卡的时候,就会打开一个“socket文件”,通过读写这个socket文件,就能读写网卡了

操作系统提供的这组API,叫做socket(套接字) API,是C语言风格的接口,在Java中是不能直接使用的。JDK针对C语言这里的socket API进行了封装。

在Java标准库有一组类,这组类能够让我们完成网络编程,这组类本质上调用的是操作系统提供的socket API。

二、那么在Java中能调用C语言的函数吗?

答案是可以,这就是跨语言调用,不同的语言之间很多都可以互相调用,而实现跨语言调用核心原理在于了解对应语言的ABI(二进制编程接口)。

三、操作系统提供的socket API主要有两类(实际上不止两类)

1.流套接字(底层使用TCP协议)

TCP协议的特点:

第一、有连接

第二、可靠传输

第三、面向字节流

第四、全双工

2.数据报套接字(底层使用UDP协议)

UDP协议的特点:

第一、无连接

第二、不可靠传输

第三、面向数据报

第四、全双工

TCP协议和UDP协议都是传输层的协议,socket API属于传输层

有连接的意思就好比打电话,你拨给对方,只有对方接听了,你俩才能交流,这个交流是实时的。

无连接的意思好比发微信,只要两个人是好友,那么发消息的一方不用管对方此时想不想接收、在不在,总之,消息都可以发送过去,只顾自己发消息成功就好了,不用管对方的状态。

可靠传输:这里千万别理解成消息能够100%发送成功(被对方收到),这是绝对不可能的,因为技术再怎么牛,也禁不住降维打击:拔网线。还有也不能理解成发送消息100%安全这里的正确理解是发送消息的一方知道接收信息的一方是不是收到消息了。这个可以结合带你电话来理解。

不可靠传输:这个理解和可靠传输相反,即发送消息的一方不知道接收信息的一方是不是收到消息了。这个可以结合发微信来理解。

千万别认为TCP比UDP更安全,可靠性不等于安全性。

面向字节流:例如要发送100个字节,可以一次发一个字节,重复100次,也可以一次发10个字节,重复10次......,可以非常灵活的完成这里的发送,接受也是同理。

TCP是面向字节流的,文件读写也是面向字节流的。

面向数据报:以一个一个的数据报为基本单位(每个数据报的大小不同的协议里面有不同的约定),发送的时候,一次至少发一个数据报,如果一次尝试发一个半数据报,实际上只能发出去一个;接收的时候,一次至少收一个数据报,如果一次尝试收一个半数据报,实际上只能收到一个,剩下的半个就没了。

全双工:其实就是双向通信,即A和B可以同时向对方发送接受数据

这个可以理解为A和B之间有两根水管,一根由A发送水给B,一根由B发送水给A,互不干扰。

TCP和UDP都是全双工。

半双工:单向通信,要么A给B发,要么B给A发,不能同时发

这个可以理解为A和B之间只有一根水管,要么由A给B发送水,要么B给A发送水,二者是不能同时发的。

应用层对应的是应用程序,我们在应用程序中使用socket API,传输层、网络层、数据链路层、物理层对应的是操作系统和硬件

socket API之所以属于传输层是因为传输层离应用层最近

UDP socket中有两个核心的类:

1.DatagramSocket  描述一个socket对象

Java标准库中的DatagramSocket对象表示一个socket文件。

这里面涉及到一个核心方法receive(),它的作用是接收数据,具体的执行过程是如果没有数据过来,那么receive()就阻塞等待,如果有数据了,receive()就返回一个DatagramSocket对象。

还有个send()方法,作用是发送数据,以DatagramPacket为单位进行发送。

操作系统提供的网络编程API叫做socket API,socket API中涉及到一个核心概念socket,socket本质上是一个文件描述符。

文件描述符的解释在“怎么读文件的资源泄露中详细介绍过”,我们这里再次说一下

某个进程被创建出来,进程就会对应一个PCB,PCB中包含了一个文件描述符表,每次打开一个文件,就会在文件描述表中分配一个表项,文件描述符表类似于一个数组,数组的下标就是文件描述符,数组的元素是一个内核结构struct file,struct file是C语言中的结构体。

另外,我们在前面还提到过“一切皆文件”的思想,操作系统在管理硬件设备和一些软件资源的时候,为了能够风格统一,于是就都用文件的方式来管理

比如:普通文件、键盘(标准输入文件)、显示器(标准输出文件),网卡也是一个硬件设备,操作系统也是用文件来管理网卡,此处用来表示网卡设备的文件,也就死socket文件。

而要想操作网卡,就首先需要创建出一个socket文件,通过读写这个socket文件的方式就可以操作网卡了。这里的socket文件就好像是遥控器,而网卡就好比电视机,我们通过遥控器来控制电视。

2.DatagramPacket  描述一个UDP数据报

UDP是面向数据报的,发送和接收数据就是以DatagramPacket对象为单位进行的。

解决了怎么发送和怎么接收的问题后,问题又来了,我们需要知道发送的时候,目标在哪里,接收的时候,这个数据从哪里来

解决这个问题的答案就是我们之前学过的ip地址和端口号,由ip地址确定主机位置,端口号确定进程。而ip地址和端口号可以由InetSocketAddress类来表示。        

基于UDP的socket来写一个非常非常简单的回显程序,即回显客户端+回显服务器

回显的意思是A给B说啥,B就回应啥(复读机)

回显程序本身没意义,写这个程序主要是为了熟悉Socket API具体的应用。

四、正常的客户端/服务器的通信流程:

客户端一启动的时候,就需要知道服务器的ip和端口号

而服务器一启动的时候,是无法知道客户端的ip和端口号的,只有客户端的请求到了,服务器才能知道对应客户端的ip和端口号。

因此服务器和客户端的关系是不对等的

这个可以通过客人于餐馆的例子来说明

对于餐馆(好比服务器)来说,今天有多少客人,它是不知道的

对于客人(好比客户端)来说,要想吃饭,就必须知道餐馆的位置

五、服务器的代码:

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;public class UdpEchoServer {private DatagramSocket socket = null;//port表示端口号//服务器在启动的时候需要绑定一个端口号//收到数据的时候,会根据这个端口号决定把这个数据交给哪个进程//虽然此处port写的类型是int,但实际上端口号是一个两个字节的无符号整数//范围是0~65535public UdpEchoServer(int port) throws SocketException {socket = new DatagramSocket(port);}//通过这个方法来启动服务器public void start() throws IOException {System.out.println("服务器启动");//服务器一般都是7*24小时运行while (true) {//1、读取请求。当前服务器不知道客户端啥时候发来请求,receive方法也会阻塞//  如果真的有请求过来了,此时receive就会返回//  参数DatagramPacket是一个输出型参数,socket中读到的数据会设置到这个对象的参数中//  DatagramPacket在构造的时候,需要指定一个缓冲区(就是一段内存空间,通常使用byte[])DatagramPacket requestPacket = new DatagramPacket(new byte[4096],4096);socket.receive(requestPacket);//把socketPacket对象里面的内容取出来,作为一个字符串String request = new String(requestPacket.getData(),0, requestPacket.getLength());//2、根据请求计算响应String response = process(request);//3、把响应写回到客户端,这时候也需要构造一个DatagramPacket//  此处给DatagramPacket中设置的长度,必须是字节的个数//  如果直接取response.length(),此处得到的是字符串的长度,也就是字符的个数//  当前的responsePacket在构造的时候,还需要指定这个包要发给谁//  其实发送给的目标就是发送请求的那一方DatagramPacket responsePacket = new DatagramPacket(response.getBytes(),response.getBytes().length,requestPacket.getSocketAddress());socket.send(responsePacket);//4、日志打印//%s 表示要打印一个字符串//%d 表示要打印一个有符号的十进制的整数String log = String.format("[%s:%d] request: %s; response: %s",requestPacket.getAddress(),requestPacket.getPort(),request,response);System.out.println(log);}}//此处process方法负责的功能就是根据请求计算响应//由于当前是一个回显服务器,就是把客户端发的请求直接返回去即可private String process(String request) {return request;}public static void main(String[] args) throws IOException {UdpEchoServer server = new UdpEchoServer(9090);server.start();}
}

六、客户端和服务器

由于是客户端先给服务器发送请求

因此客户端就需要先知道服务器的ip和端口

服务器如果收到了客户端的请求,那么就知道客户端的ip和端口了

七、客户端的代码:

import java.io.IOException;
import java.net.*;
import java.util.Scanner;public class UdpEchoClient {private DatagramSocket socket = null;private String serverIp;private int serverPort;//参数serverIp和serverPort,是服务器的ip和端口号public UdpEchoClient(String serverIp, int serverPort) throws SocketException {this.serverIp = serverIp;this.serverPort = serverPort;this.socket = new DatagramSocket();//这里为什么没有端口号这个参数呢?//客户端在构造这个Socket对象的时候,不需要指定端口号,尤其是不能把serverPort指定进去//举一个例子//A(客户端)给B(服务器)发一个快递//A首先需要知道B的收货地址(serverIp)和收货电话(serverPort)//然后在快递包裹上写上收件人的信息以及发件人的发货地址(ip)和发货电话(port)//而上述DatagramSocket()构造方法中传入的port,这是指定自己的端口//如果A在DatagramSocket()这个构造方法中传入了serverPort,这就是相当于把自己发件人的电话写成了收件人电话//如果当前DatagramSocket()构造方法中没有指定端口的话,操作系统会分配一个空闲的端口号给客户端使用//为啥客户端的端口号可以随机生成,而服务器这里就必须手动指定呢?//客户端需要明确知道服务器的端口号是啥,才能通信//这就好比A给B发快递,必须要知道B的电话是啥,要不然咋发//而B不必知道A的电话//刚才构造Socket时,我们都是围绕端口来操作的,那么ip呢?//答案是服务器这边的ip相当于被自动设置为本机的ip//客户端这边的ip也自动设置为本机的ip,但是需要手动指定一下服务器的ip.}public void start() throws IOException {Scanner scanner = new Scanner(System.in);while (true) {//1.从标准输入读入一个数据System.out.println("->");String request = scanner.nextLine();if (request.equals("exit")) {System.out.println("exit");return;}//2.把字符串构造成一个UDP请求,并发送数据//      这个DatagramPacket中,既要包含具体的数据,又要包含这个数据要发给谁DatagramPacket requestPacket = new DatagramPacket(request.getBytes(),request.getBytes().length,InetAddress.getByName(serverIp),serverPort);socket.send(requestPacket);//3.尝试从缓冲区读取响应//      DatagramPacket在构造的时候,需要指定一个缓冲区(就是一段内存空间,通常使用byte[])DatagramPacket responsePacket = new DatagramPacket(new byte[4096],4096);socket.receive(responsePacket);String response = new String(responsePacket.getData(),0, responsePacket.getLength());//4.显式这个结果String log = String.format("req: %s, resp: %s",request,response);System.out.println(log);}}public static void main(String[] args) throws IOException {//127.0.0.1是环回ip,环回ip表示的是主机本身//当前客户端和服务器在同一台主机上//所以在客户端写的服务器ip是127.0.0.1//如果在不同主机上,就需要写成对应服务器的ipUdpEchoClient client = new UdpEchoClient("127.0.0.1",9090);client.start();}}

把服务器的程序运行,然后把客户端的程序运行,输入数据得到的结果是

客户端的界面:

服务器的界面:

 当使用同一台主机部署客户端和服务器的时候,此时虽然是网络的那套逻辑,但实际上仍然是一台主机内部的通信。

只有把服务器代码部署到一个云服务器上,然后通过客户端程序来访问云服务器,此时就是两台主机来通信了。

想要部署程序,需要把程序打个jar包,把jar拷贝过去就行。

总结

DatagramSocket:对socket文件进行了封装

构造方法分为

1)无参:客户端使用,此时端口号由系统分配

2)有参(传入端口号):服务器使用,此时端口号由用户指定

DatagramSocket有两个核心方法:

receive:可能会阻塞

读取一个UDP数据,并且放到DatagramSocket中去

send:

发送一个UDP数据

DatagramPacket对一个UDP数据报进行了封装

它的构造方法是

1)传入空的缓冲区,构造一个空的packet(receive的时候使用)

2)传入一个有数据的缓冲区,指定一下目标的ip和端口,在send的时候使用

3)传入一个有数据的缓冲区,制定一下目标的ip和端口(通过InetSocketAddress这个类来得到),在send的时候使用。


http://chatgpt.dhexx.cn/article/SX7o1C50.shtml

相关文章

北斗系统学习—JT808协议用C语言解析

前言: 本人从事于Linux应用开发(音视频应用方向),现在主要是负者AI摄像头的开发,在学音视频的途中,虽然是个小白,但是更愿意把自己所学音视频的一些知识分享给大家,以后每周都会更新哦! 本期介绍…

TCP/IP协议(一、自己动手实现udp)

对TCP/IP协议都只是听过,没有仔细研究过,一些知识体系也比较零散,什么三次握手,四次挥手,滑动窗口,零拷贝技术等等,都是知识有这么个东西,而不知道具体是啥,这几天还是根…

【Linux】传输层协议:UDP和TCP

但人不能永远浪漫下去,那会走向自我毁灭的。浪漫都是水字旁,会把人淹死的。人最终还是要进入一个规则体系,所谓,随心所欲不逾矩嘛 文章目录 一、UDP协议1.端口号2.理解UDP报头3.UDP的特点(面向数据报,全双…

Linux网络:UDP协议 | TCP协议

文章目录 前言端口号netstat -- pidof UDP协议TCP协议三次握手 四次挥手确认应答(ACK)机制超时重传机制连接管理机制理解TIME_WAIT状态理解 CLOSE_WAIT 状态 滑动窗口流量控制拥塞控制延迟应答捎带应答面向字节流粘包问题TCP异常情况TCP小结 基于TCP 和 UDP 的应用层协议TCP/UD…

C语言SOCKET编程指南

转载自:http://blog.sina.com.cn/s/blog_79b01f66010163q3.html 这篇文章完全可以作为c语言socket编程指南,无论在任何系统下。感谢作者fenglovel! C语言SOCKET编程指南 1、介绍 Socket 编程让你沮丧吗?从man pages中很难得到有…

【socket】从计算机网络基础到socket编程——Windows Linux C语言 + Python实现(TCP+UDP)

一、部分基础知识1.1 计算机网络的体系结构1.11 互联网简介1.12 计算机网络的分类1.13 协议与网络的分层体系结构▶ 协议▶ 网络的分层体系结构 1.14 OSI 七层模型(重要)▶ OSI 模型的结构▶ OSI 模型各层的功能 1.15 TCP/IP 的体系结构(重要…

C语言 C语言基础

C语言 C语言基础 一、简述 对于C语言基础相关方面的表面理解,简单介绍。 二、二进制 生活中常用的是十进制,基数0,1,2,3,4,5,6,7,8,9,。满10进1。 时钟60进制。基数0,1,2...57,58,59。满60进1。60秒为1分钟,60分钟为1小时。 计算机二进制&a…

炼一项专业技能c语言,C语言程序设计_安徽新华电脑专修学院

C语言程序设计,安徽新华电脑专修学院,2013年3月,在安徽省315国际消费者权益日纪念大会暨省消协四届三次理事会会议上,安徽新华电脑专修学院被省消费者协会授予“诚信单位”。 C语言程序设计, 并用c语言进行测试。还有b…

C++中使用UDP Socket发送字节数据

文章目录 参考代码结果展示 参考 这篇文章给的代码也能用 https://blog.csdn.net/qq_36437446/article/details/106446172 CRC代码来自https://blog.csdn.net/huijunma2010/article/details/124151471 在线计算CRC http://www.ip33.com/crc.html 代码 这里的byte是unsigned…

本机UDP收发性能测试

测试内容 测试单机版的UPD客户端和服务端之间的性能,UDP客户端发送数据到UDP服务端,并等待服务端返回,计算出UDP的性能 测试方法 客户端和服务端部署在同一台虚拟机器上,客户端启动多个线程,同时向服务端发送指定数量…

2020复旦大学计算机夏令营机试题

2020复旦大学计算机夏令营机试题 这个是开卷编程,不计入成绩,但是面试会问你做的情况。

复旦大学机试题题解(2017~2021)

前言 尝试把复旦大学历年的机试题做一遍,能做多少是多少了,因为没有数据集所以也不好确认是不是对的~(题目来自王道往届学长学姐回忆以及某位热心的同学整理,如果了解来源后,我一定备注来源) (…

复旦大学:专硕没住宿?我们帮你建!还给补助!

去年,小编发过一篇文章,里面爆出了复旦大学等学校的专硕可能不提供住宿了: 北京大学 上海交通大学 复旦大学 专硕可能不提供住宿! 后来,在复旦大学2019年招收攻读硕士学位研究生简章中,学校官方公布了不为专…

复旦大学机试题(2017-2021)

计院2021 1.完全二叉树 给定一颗二叉树,树的每个节点的值为一个正整数。如果从根节点到节点 N 的路径上不存在比节点 N 的值大的节点,那么节点 N 被认为是树上的关键节点。求树上所有的关键节点的个数。请写出程序,并解释解题思路。 例子&a…

三战上岸复旦工研院考研回忆(无干货)

干货链接: 复旦085400电子信息专硕初试经验分享 复旦085400电子信息专硕复试经验分享 复旦软院电子信息初试961真题回忆 说说一下我的考研经历,都是流水账,不涉及干货(干货参照其他博客),如果读者能有所借…

2020年复旦大学夏令营机试题及代码(VS2019 C++)

注:代码是本菜鸡自己个儿写的,没有找到参考答案,欢迎各位大佬批评指正. 题目如下图所示(图片来源网上): 第1题 该题主要考察拓扑排序.其实该算法有通用模板,但我写的时候没有意识到使用,代码不是很规范. #define _CRT_SECURE_NO_WARNINGS#include &…

复旦大学研究生机试(2019)

1. 计算机学院 今年的题目可以说是挺难的,第一题虽然像是送分题,实际上也不是很简单。第二题第三题是动态规划问题,而且复旦据说会卡大数,今年150人考生据说只有一个AC,大部分人只做出第一题,个别零分。 …

【20保研】2019年复旦大学工程与应用技术研究院全国优秀大学生夏令营通知

点击文末的阅读原文或者公众号界面左下角的保研夏令营或者公众号回复“夏令营”是计算机/软件等专业的所有保研夏令营信息集合,会一直更新的。 为了促进我国高校优秀大学生之间的交流、加强学生对复旦大学工研院的了解、特别是吸引优秀学生继续深造,探索…

复旦大学计算机专业硕士平均工资,在复旦大学当教授“月薪”是多少?这个工资条,让网友非常羡慕!...

文章原创,版权归本作者所有,欢迎个人转发分享 随着中国的高等教育发展的重视,很多的高校也是不负众望,不仅在国内知名度很高,在国外也享有盛誉的。 在中国知名度最高的大学就是清华、北大、复旦等高校,是受…

复旦计院、工研院2019机试真题及答案详解

计院 A 相隔天数 输入一个 yyyymmdd 格式的时间&#xff0c;如 20190318&#xff0c;计算与 20190205 相差的天数&#xff0c; 取绝对值&#xff0c;所有输入在 19000101 和 21000101 之间。 样例输入&#xff1a;20190208 输出&#xff1a;3 #include<iostream>us…