第 19 章 网络编程

网络可以使不同物理位置上的计算机达到资源共享和通信的目的,在Java中也提供了专门的网络开发程序包--java.net,以方便开发者进行网络程序的开发,本章将讲解TCP与UDP程序开发

19.1 网络编程简介

        将地理位置不同的、具有独立功能的多台计算机连接在一起就形成了网络,网络形成后网络中的各台主机就需要具有通信功能,所以才为网络创造一系列的通信协议。在整个通信过程中往往会分为两种端点:服务端与客户端,所以围绕着服务端和客户端的程序开发就有了两种模式。
        C/S(Client/Server):要开发两套程序,一套是服务器端;另一套是与之对应的客户端,但是这种模式在进行维护的时候,需要维护两套程序,而且客户端的程序更新也必须及时,此类程序安全性能好。
        B/S(Browser/Server):只需针对服务器端开发一整套程序,客户端使用浏览器进行访问。这种程序在日后进行程序维护的时候只需维护服务器端即可,客户端不需要做任何修改。此类程序使用公共端口,包括公共协议,所以安全性很差。
本章重点讲解C/S接口的程序的两种实现:TCP模型和UDP模型
提问:HTTP是什么
在日常使用中,很多时候使用HTTP进行访问,HTTP通信和TCP通信有什么联系。
回答:TCP是HTTP通信的基础协议
        实际上HTTP通信也是基于TCP协议的一种应用,是在TCP协议基础上追加了一些HTTP标准后形成的HTTP通信。HTTP通信不仅仅在B/S结构上被广泛应用,同时在一些分布式开发中也使用较为广泛。JavaWeb开发(JSP、Servlet、Ajax等)就是java针对HTTP协议提供的开发支持。
        顺带提醒的是,Java只提供最为核心的网络开发支持,而如果真的要想开发一个具有稳定通信能力的网络程序是,开发者必须精通各种通信协议。为了简化此类开发,开源世界提供了一个Netty开发框架,可以帮助开发者轻松实现各种常见的TCP、UDP、HTTP、WebSocket通信协议。

19.2 Echo程序模型

在TCP编程模型中,Echo是一个经典的程序案例,Echo程序模型的基本思想在于,客户端通过键盘输入一个信息,把此信息发送给服务器端后,服务器端会将此信息反馈给客户端进行显示,本操作主要通过java.net包的两个类实现。
        ServerSocket类:封装TCP协议类,工作在服务器端,常用的方法如表
        Socket类:封装TCP协议的操作类,每一个Socket对象都表示一个客户端

Echo通信模型的实现需要通过ServerSocket类在服务器端定义数据监听端口,在没有客户端连接时将一直处于等待连接状态。每一个客户端连接到服务器端后都通过Socket实例描述,通过Socket可以获取客户端和输出端的实例,这样就可以实现I/O通信
        范例:定义Echo服务器端

package cn.mldn.demo;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.util.Scanner;
public class EchoServer
{
public static void main(String[]args)throws Exception
{
ServerSocket server=new ServerSocket(9999);//设置服务器监听端口
System.out.println("等待客户端连接。。。。。。。。。");
Socket client=server.accept();
//首先需要先接收客户端发送来的信息,而后才可以将信息处理后发送给客户端
Scanner scan=new Scanner(client.getInputStream());//客户端输入流
scan.useDelimiter("\n");//设置分隔符
PrintStream out=new PrintStream(client.getOutputStream());//客户端输出流
boolean flag=true;
while(flag)
{
if(scan.hasNext())
{
String val=scan.next().trim();//接收数据内容
if("byebye".equalsIgnoreCase(val))
{
out.println("byebyebye");
flag=false;
}else
{
out.println("echo"+val);
}
}
}

scan.close();
out.close();
client.close();
server.close();
}
}

本程序在主线程实例化了一个ServerSocket类对象,并且设置了在本季的9999端口上进行监听,当有客户端连接到服务器端后(accept()方法在客户端连接前会一直泽色程序运行),会获取客户端Socket的输入流和输出流,进行数据的接收与回应处理。

提示:使用telnet命令测试

在Windows、Linux等系统中都会提供一个telnet的测试命令,进行服务器端的使用测试,开发者只需要输入telnet localhost9999命令即可直接与服务器端程序连接。如果在Windows系统中此命令默认不开启,则开发者选择启用或关闭Windows功能。服务端的主要功能是进行客户端发送数据的回显处理,客户端需要实现键盘数据的输入并且通过Socket实例实现数据的发送与回应处理。

范例:编写客户端程序

package cn.mldn.demo;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;
import java.util.Scanner;
public class EchiClient
{
private static finale BufferedReader KEYBORAD_INPUT=new BufferedReader(new InputStreamReader(System.in));
public static String getString(String prompt)throws Exception
{
//键盘信息的输入
System.out.print(prompt);
String str=KEYBOARD_INPUT.readLine();
return str;
}
public static void main(String[]args)throws Exception
{
Socket client=new Socket("localhost",9999);//定义服务器端的连接信息
//现在的客户端需要有输入与输出的操作支持,所以依然要准备出Scanner和PrintWriter
Scanner scan=new Scanner(client.getInputStream());//接收服务器端输入内容
scan.useDelimiter("\n");
PrintStream out=new PrintStream(client.getOutputStream());//向服务器端发送内容
boolean flag=true;//循环标记
while(flag)
{
String input=getString("请输入要发送的内容").trim();//获取键盘输入数据
out.println(input);//加换行
if(scan.hasNext())
{
System.out.println(scan.next());//输出回应消息
}
if("byebye").equlasIgnoreCase(input){flag=false;}
}
}

scan.close();
out.close();
client.close();
}

19.3 BIO处理模型

此时的Echo模型是基于单线程(主线程)的处理机制实现的网络通信,这样会造成一个问题,在同一段时间内只允许有一个客户端连接到服务器端并进行通信处理,并且当次客户端退出后服务器端也会随之关闭,所以为了提升服务器段的处理性能,就可以利用多线程来处理多个客户端的通信需求

根据上图可以发现,在服务器端中的每一个ServerSocket需要连接多个Socket,同时可以将每一个客户端的Socket实例封装在一个线程中,这样一个服务器端就可以同时处理多个客户端请求。

范例:修改服务器端实现

package cn.mldn.demo;
import java.io.IOException;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.util.Scanner;
public class EchoServer
{
private static vlass ClientThread implements Runnable
{
private Socket client=null;//客户端Socket
private Scanner scan=null;//输入流
private PrintStream out=null;//输出流
private boolean flag=true;
public ClientThread(Socket client)throws Exception
{
this.client=client;//保存Socket
this.scan=new Scanner(client.getInputStream());//输入流
this.scan.useDelimiter("\n");//设置分隔符
this.out=new PrintStream(client.getOutputStream());//输出流
}

@Override 
public void run()
{
while(this.flag)
{
if(scan.hasNext())
{
String val=scan.next().trim();
if("byebye".equalsIgnoreCase(val))
{
out.println("byebyebye");
this.flag=false;
}else
{
out.println("【ECHO】"+val);
}
}
}
scan.close();
out.close();
client.close();
}
}
}

public static void main(String[]args)throws Exception
{
ServerSocket server=new ServerSocket(9999);//设置服务监听端口
System.out.println("等待客户端连接......");
boolean flag=true;
while(flag)
{
Socket client=server.accept();//有客户端连接
new Thread(new ClientThread(client)).start();
}
server.close();
}

本程序服务器端将采用玄幻的形式实现多个Socket客户端的连接,并且将每一个接受到的Socket实例封装到独立的线程中进行独立的Echo回应处理。

提示:本模型属于BIO模型
        在本程序中虽然是用了多线程修改了服务器端处理模式,但是在程序开发中并没有对服务器端可用线程数量进行限制,这也就意味着如果并发客户端访问量增加,则服务器端将会出现严重的性能问题。所以JDK1.4以前就必须对县城熟练进行有效控制,需要追加客户端等待了解机制才可以正常使用,这种模式称为BIO(Blocking IO,阻塞IO)模式。

19.4 UDP程序

TCP的所有操作都必须建立可靠的连接才可以通信,但是这种做法肯定会浪费大量的系统性能,为了减少这种开销,在网络中又提供了另外一种传输协议--UDP(不可靠连接),即利用数据报的形式进行数据发送,由于没有建立可靠连接,此时接收端可能处于关闭状态,所以利用UDP发送的数据,客户端不一定接收到。在Java中使用DatagramPacket类和DatagramSocket类,完成UDP程序的开发
提示:关于UDP开发中服务器端和客户端的解释
        使用UDP开发的网络程序,类似于平常使用手机,手机实际上相当于一个客户端,如果现在手机要是想正常收信息,则手机肯定要先打开才行。

范例:实现一个UDP客户端进行信息接收

在进行UDP客户端编写时需要设置一个客户端的监听端口,结束到的数据信息可以利用DatagramPacket类对象进行接收,这样在客户端打开的情况下会自动接收到服务器端发送来的消息。

package cn.mldn.demo;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
public class UDPClient
{
public static void main(String[]args)throws Exception
{
DatagramSocket client=new DatagramSocket(9999);//接收数据信息
byte data[]=new byte[1024];//保存接收数据
DatagramPacket packet=new DatagramPacket(data,data.length);//创建数据报
System.out.println("客户端等待接收发送的消息");
client.receive(packet);//接收消息内容
System.out.println("接受到的信息内容为"+new String(data,0,packet,getLength()));
client.close();
}
}

在进行UDP客户端编写时需要设置一个客户端的监听端口,接收到的数据信息可以利用DatagramPacket类对象进行接收,这样在客户端打开的情况下会自动接收到服务器端发来的信息。

范例:编写一个UDP服务器端程序发送数据报

package cn.mldn.demo;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
public class UDPServer
{
public static void main(String[]args)throws Exception
{
DatagramSocket server=new DatagramSocket(9000);
String str="AAA";
DatagramPacket packet=new DatagramPacket(str.getBytes(),0,str.length(),InetAdress.getByName(localhost),9999);
server.send(packet);
server.close();
}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/142962.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

三菱PLC小项目系列—传送带多地控制

目录 一、项目描述 二、IO口分配 三、项目程序 四、总结 一、项目描述 化工厂中有传送带进行原料传送加工,当按下启动按钮SB1或者SB2,电机M1接通控制传送带运转,直至按下停止按钮SB3,电机停止并使传送带停止运行。 二、IO口分…

远程创建分支本地VScode看不到分支

在代码存放处右击,点击Git Bash Here 输入git fetch–从远程仓库中获取最新的分支代码和提交历史 就OK啦,现在分支可以正常查看了

多行业用户齐聚,2023 IoTDB 用户大会详细议程更新!

上周我们官宣了 2023 IoTDB 用户大会举办的消息,获得了多方小伙伴们积极的响应,作为第一次线下大会,我们已经开始期待与大家线下相见! 为了回应大家对于大会内容的期待,我们火速把更加详细的议程“搬运”来啦~ 20 位大…

【Java】集合(一)单列集合List

1.集合 可以动态保存任意多个对象,并提供了一系列的操作对象的方法:add、remove、set、get等。 2.集合框架体系 分为两大类: 单列集合和双列集合 3.List接口基本介绍 List接口是Collection接口的子接口 List集合类中元素有序&#xff0…

前后端设置跨域问题

前端 const {defineConfig} require(vue/cli-service) module.exports defineConfig({transpileDependencies: true,devServer: { //记住,别写错了devServer//设置本地默认端口 选填port: 8080,proxy: { //设置代理,必…

【git】git本地仓库命令操作详解

这篇文章主要是针对git的命令行操作进行讲解,工具操作的基础也是命令行,如果基本命令操作都不理解,就算是会工具操作,真正遇到问题还是一脸懵逼 1.操作逻辑图 本地仓库的命令操作关系图 2.基本命令操作 1.1建立一个gittest01文…

二维码智慧门牌管理系统升级解决方案:标准地址ID查询服务:高效、精准

文章目录 前言一、解决查询效率低下的问题二、提高信息精准度三、应用案例 前言 随着城市的发展和信息化步伐的加快,二维码智慧门牌管理系统已成为各大城市管理部门和企事业单位的必备工具。然而,实际应用中存在一些问题,如查询效率低下、信…

navicat导入已有sql表过程

已知我有一个外部的sql表,如图: 想要将其导入navicat并运行。 看一下我的navicat, navicat里已有的数据库并没有library,所以需要建立一个同名的library数据库来存储library.sql文件。 具体步骤如下: 在“本地连接”…

「Verilog学习笔记」优先编码器Ⅰ

专栏前言 本专栏的内容主要是记录本人学习Verilog过程中的一些知识点,刷题网站用的是牛客网 分析 分析编码器的功能表: 当使能El1时,编码器工作:而当E10时,禁止编码器工作,此时不论8个输入端为何种状态&…

U盘格式化数据恢复软件EasyRcovery2024免费版

出差办公,我习惯将所有的文件都拷贝到U盘里随身携带,这样就省去了带电脑的麻烦。U盘虽然方便携带,但也有一个致命的缺陷,就是删除的文件会被彻底清理,而不是保存在回收站。一旦不小心将U盘格式化,对我来说就…

C++入门(1)

目录 一、什么是C 1、C关键字(C98) 2、C兼容C 二、C程序预处理指令 三、命名空间 1、命名冲突 第一种: 第二种: 2、域作用限定符 3、实现命名空间 4、命名空间冲突 5、访问命名空间 6、命名空间“std” 四、输入输出 1、定义 2、自动识…

目标检测——Yolo系列(YOLOv1/2/v3/4/5/x/6/7/8)

目标检测概述 什么是目标检测? 滑动窗口(Sliding Window) 滑动窗口的效率问题和改进 滑动窗口的效率问题:计算成本很大 改进思路 1:使用启发式算法替换暴力遍历 例如 R-CNN,Fast R-CNN 中使用 Selectiv…

activiti命令模式与责任链模式

来源:activiti学习(七)——命令模式和职责链模式在activiti中的应用 文章目录 设计模式命令模式CommandHelloCommandByeCommand ReceiverInvokerClient 职责链模式AbstractHandlerConcreteHandlerAConcreateHandlerB Client activiti中很多ap…

SQLServer添加Oracle链接服务器

又一次在项目中用到了在SQLServer添加Oracle链接服务器,发现之前文章写的也不太好使,那就再总结一次吧。 1、安装OracleClient 安装64位,多数SQLServer是64位,所以OracleClient也安装64位的; 再一个一般安装的Oracl…

demo(一)eureka----服务注册与提供

下面写一个简单的demo验证下eureka&#xff0c;实现服务注册、服务发现。 一、单节点&#xff1a; 1、api&#xff1a; 封装其他组件需要共用的dto 2、eureka-service服务注册中心&#xff1a; &#xff08;1&#xff09;pom: <?xml version"1.0" encoding&q…

主从复制和读写分离

MySQL 主从复制和读写分离&#xff1a; 主从复制&#xff1a;主MySQL上的数据&#xff0c;新增&#xff0c;修改库&#xff0c;表&#xff0c;表里的数据&#xff0c;都会同步到从MySQL上。 MySQL的主从复制的模式&#xff1a;&#xff08;面试题&#xff09; 1&#xff0c;异…

【第2章 Node.js基础】2.4 Node.js 全局对象(二) process 对象

process对象是一个全局对象&#xff0c;提供当前Node.js 进程信息并对其进行控制。通常用于编写本地命令行程序。 1.进程事件 process对象是EventEmitter类的实例&#xff0c;因此可以使用事件的方式来处理和监听process对象的各种事件。以下是一些常用的process对象事件&…

3.4 Linux 软件管理

一. RPM 软件包管理器 1、软件包介绍 RPM&#xff08;RedHat Package Manager&#xff09;软件包&#xff1a;扩展名为“.rpm”。RPM本质上就是一个包&#xff0c;包含可以立即在特定机器体系结构上安装和运行的Linux软件。安装RPM软件包需要使用rpm命令或yum命令。 源代码软…

荧光量子效率积分球的优势是什么

荧光量子效率积分球是一种测量设备&#xff0c;可以用于测量荧光材料在特定波长下的量子效率。它由一个具有高朗伯特性的漫反射PTFE材料制成&#xff0c;具有高达99%的反射率和朗伯特性。积分球有三个开口&#xff0c;分别为光入射口、样品口和光出射口。光入射口设置有一准直镜…

windows10上使用Visual Studio对树莓派进行交叉编译示例

本文主要介绍通过Visual Studio对树莓派进行交叉编译的方法。 1 环境 宿主机&#xff1a; 系统&#xff1a;Windows10 开发平台&#xff1a;Visual Studio 2022 (我用的是社区版) VisualGDB: VisualGDB - Download (我下的试用版本) GNU工具链: Prebuilt GNU toolchain f…