第二十一章 网络通信

发布时间:2023年12月27日

网络通信这一章 ?基本分为三个部分 ?网络基础概念和TCP,UDP这三个部分主要如下:

计算机网络实现了堕胎计算机间的互联,使得它们彼此之间能够进行数据交流。网络应用程序就是再已连接的不同计算机上运行的程序,这些程序借助于网络协议,相互之间可以交换数据,编写网络应用程序前,首先必须明确网络协议TCP/IP协议是网络应用程序的首选

网络程序设计基础:

网络程序设计编写始于其他计算机进行通信的程序,java已经将网络程序所需要而定元素封装成不同的类,用户只要床啊金这些类的对象,使用相应的方法即使不举报相关的网络知识,也是可以编写除高质量的网络通信程序的,

本章最主要的是TCP和UDP两个部分 ?他们两主要的区别就是一个是一对一通信 ?一个是一对多通信 ? 当然两者都有各自的优势和劣势,接下来先讲解 TCP部分
TCP程序

TCP程序的通信方式呢 是一对一的 ? 步骤是 ?先要打开服务器然后客户端连接服务器 ?先是尝试客户端是否能够接收到信息 ?如果可以接收到信息的话 ?这时服务器将会把文件传输给客户端,这样的话 能够保证客户端可以接收到信息 ?,劣势呢就是每次都是要这样子 所以效率对比起UDP来说慢下了好多 ?以下代码将会进行讲解

客户端代码:package tcp;
?
import java.io.*;
import java.net.Socket;
import java.util.Scanner;
?
/**
?* Socket客户端
?**/
public class SocketClient {
? ? public static void main(String[] args) {
? ? ? ? Socket s = null;
? ? ? ? try {
? ? ? ? ? ? // 与ip为127.0.0.1、端口服务端代码:z为12345的服务端建立连接
? ? ? ? ? ? s = new Socket("127.0.0.1", 12345);
?
? ? ? ? ? ? // 创建输入流接收服务端发送的消息(字节流)
? ? ? ? ? ? InputStream is = s.getInputStream();
? ? ? ? ? ? // 将服务端返回的字节流转化为字符流
? ? ? ? ? ? InputStreamReader isr = new InputStreamReader(is);
? ? ? ? ? ? // 创建字符流读取缓冲区,方便每行读取
? ? ? ? ? ? BufferedReader br = new BufferedReader(isr);
?
? ? ? ? ? ? // 创建输出流返回消息
? ? ? ? ? ? OutputStream os = s.getOutputStream();
? ? ? ? ? ? // 创建输出流缓冲
? ? ? ? ? ? PrintWriter pw = new PrintWriter(os);
?
? ? ? ? ? ? // 创建发送消息的线程
? ? ? ? ? ? Runnable rOut = () -> {
? ? ? ? ? ? ? ? boolean flag = true;
? ? ? ? ? ? ? ? while (flag) {
? ? ? ? ? ? ? ? ? ? try {
? ? ? ? ? ? ? ? ? ? ? ? // 接收控制台输入
? ? ? ? ? ? ? ? ? ? ? ? Scanner scan = new Scanner(System.in);
? ? ? ? ? ? ? ? ? ? ? ? String msg = scan.nextLine();
? ? ? ? ? ? ? ? ? ? ? ? // 将输入写入缓冲
? ? ? ? ? ? ? ? ? ? ? ? pw.println(msg);
? ? ? ? ? ? ? ? ? ? ? ? // 将缓冲内的数据推送至服务端并清空缓冲区
? ? ? ? ? ? ? ? ? ? ? ? pw.flush();
? ? ? ? ? ? ? ? ? ? } catch (Exception e) {
? ? ? ? ? ? ? ? ? ? ? ? flag = false;
? ? ? ? ? ? ? ? ? ? ? ? e.printStackTrace();
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? }
? ? ? ? ? ? };
?
? ? ? ? ? ? // 创建接收消息的线程
? ? ? ? ? ? Runnable rIn = () -> {
? ? ? ? ? ? ? ? boolean flag = true;
? ? ? ? ? ? ? ? while (flag) {
? ? ? ? ? ? ? ? ? ? try {
? ? ? ? ? ? ? ? ? ? ? ? // 逐行读取服务端返回的消息并打印
? ? ? ? ? ? ? ? ? ? ? ? String str = br.readLine();
? ? ? ? ? ? ? ? ? ? ? ? System.out.println("服务端的消息:" + str);
? ? ? ? ? ? ? ? ? ? } catch (IOException e) {
? ? ? ? ? ? ? ? ? ? ? ? flag = false;
? ? ? ? ? ? ? ? ? ? ? ? e.printStackTrace();
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? }
? ? ? ? ? ? };
?
? ? ? ? ? ? // 启动两个线程
? ? ? ? ? ? Thread tOut = new Thread(rOut);
? ? ? ? ? ? Thread tIn = new Thread(rIn);
? ? ? ? ? ? tOut.start();
? ? ? ? ? ? tIn.start();
? ? ? ? }catch (IOException e) {
? ? ? ? ? ? try {
? ? ? ? ? ? ? ? // 释放资源
? ? ? ? ? ? ? ? s.close();
? ? ? ? ? ? } catch (Exception exception) {
? ? ? ? ? ? ? ? exception.printStackTrace();
? ? ? ? ? ? }
? ? ? ? ? ? e.printStackTrace();
? ? ? ? }
? ? }
}服务端代码:package tcp;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
?
/**
?* Socket服务端
?**/
public class SocketServer {
? ? public static void main(String[] args) {
? ? ? ? ServerSocket ss = null;
? ? ? ? Socket s = null;
? ? ? ? try {
? ? ? ? ? ? // 创建监听端口为12345的Socket服务端
? ? ? ? ? ? ss = new ServerSocket(12345);
? ? ? ? ? ? System.out.println("服务端Socket服务已建立,等待客户端连接...");
? ? ? ? ? ? // 通过ss.accept()开始持续监听12345端口,当有连接时获取收到的包装成Socket的客户端对象
? ? ? ? ? ? s = ss.accept();
? ? ? ? ? ? // 获取客户端的IP地址和端口号
? ? ? ? ? ? String ip = s.getInetAddress().getHostAddress();
? ? ? ? ? ? int port = s.getPort();
? ? ? ? ? ? System.out.println("服务端与 " + ip + ":" + port + " 已建立连接");
?
? ? ? ? ? ? // 创建输入流接收客户端发送的消息(字节流)
? ? ? ? ? ? InputStream is = s.getInputStream();
? ? ? ? ? ? // 将客户端发送的字节流转化为字符流
? ? ? ? ? ? InputStreamReader isr = new InputStreamReader(is);
? ? ? ? ? ? // 创建字符流读取缓冲区,方便每行读取
? ? ? ? ? ? BufferedReader br = new BufferedReader(isr);
?
? ? ? ? ? ? // 创建输出流返回消息
? ? ? ? ? ? OutputStream os = s.getOutputStream();
? ? ? ? ? ? // 创建输出流缓冲
? ? ? ? ? ? PrintWriter pw = new PrintWriter(os);
?
? ? ? ? ? ? // 创建接受信息的线程
? ? ? ? ? ? Runnable rIn = () -> {
? ? ? ? ? ? ? ? boolean flag = true;
? ? ? ? ? ? ? ? while (flag) {
? ? ? ? ? ? ? ? ? ? try {
? ? ? ? ? ? ? ? ? ? ? ? // 逐行读取客户端发送的消息并打印
? ? ? ? ? ? ? ? ? ? ? ? String str = br.readLine();
? ? ? ? ? ? ? ? ? ? ? ? System.out.println("客户端的消息:" + str);
? ? ? ? ? ? ? ? ? ? } catch (IOException e) {
? ? ? ? ? ? ? ? ? ? ? ? flag = false;
? ? ? ? ? ? ? ? ? ? ? ? e.printStackTrace();
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? }
? ? ? ? ? ? };
?
? ? ? ? ? ? // 创建发送消息的线程
? ? ? ? ? ? Runnable rOut = () -> {
? ? ? ? ? ? ? ? boolean flag = true;
? ? ? ? ? ? ? ? while (flag) {
? ? ? ? ? ? ? ? ? ? try {
? ? ? ? ? ? ? ? ? ? ? ? // 接收控制台输入
? ? ? ? ? ? ? ? ? ? ? ? Scanner scan = new Scanner(System.in);
? ? ? ? ? ? ? ? ? ? ? ? String msg = scan.nextLine();
? ? ? ? ? ? ? ? ? ? ? ? // 将输入写入缓冲
? ? ? ? ? ? ? ? ? ? ? ? pw.println(msg);
? ? ? ? ? ? ? ? ? ? ? ? // 将缓冲内的数据推送至客户端并清空缓冲区
? ? ? ? ? ? ? ? ? ? ? ? pw.flush();
? ? ? ? ? ? ? ? ? ? } catch (Exception e) {
? ? ? ? ? ? ? ? ? ? ? ? flag = false;
? ? ? ? ? ? ? ? ? ? ? ? e.printStackTrace();
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? }
? ? ? ? ? ? };
?
? ? ? ? ? ? // 开启两个线程
? ? ? ? ? ? Thread tIn = new Thread(rIn);
? ? ? ? ? ? Thread tOut = new Thread(rOut);
? ? ? ? ? ? tIn.start();
? ? ? ? ? ? tOut.start();
? ? ? ? } catch (IOException e) {
? ? ? ? ? ? try {
? ? ? ? ? ? ? ? // 释放资源
? ? ? ? ? ? ? ? ss.close();
? ? ? ? ? ? ? ? s.close();
? ? ? ? ? ? } catch (Exception exception) {
? ? ? ? ? ? ? ? exception.printStackTrace();
? ? ? ? ? ? }
? ? ? ? ? ? e.printStackTrace();
? ? ? ? }
? ? }
}???????代码图如下:???????

运行结果如下所示:

?接下来讲解UDP程序

UDP程序

UDP程序跟TCP程序不同的地方呢 ?TCP通信是一对一通信 如果要一下通知好多个人的话 就需要一个一个来通信 ?所以这时将会需要UDP了 ?UDP的优势就在于效率高 但是不稳定的地方呢 ?就是效率高但是不一定每个人都能看到 ?就像老师在台上讲课 总有一些学生会在台下玩手机 或者带耳机 ?不一定每一个人都能够接受得到 ?这就是UDP的不稳定的地方 ,接下来使用代码来讲解:

广播类代码如下:package udp;
?
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.MulticastSocket;
//广播 ?先运行
public class Notification ?extends Thread{
?? ?String weather = "节目预报:八点有大型晚会,请收听";//发送消息
?? ?int port = 9898;//端口号
?? ?InetAddress iaddress = null;
?? ?MulticastSocket socket = null;//多点广播套接字
?? ?
?? ?Notification(){
?? ??? ?try {
?? ??? ??? ?iaddress = InetAddress.getByName("224.255.10.0");//地址
?? ??? ??? ?socket = new MulticastSocket(port);//实例化多点广播套接字
?? ??? ??? ?socket.setTimeToLive(1);//指定发送范围是本地网络
?? ??? ??? ?socket.joinGroup(iaddress);//加入广播组
?? ??? ?}catch(IOException e){
?? ??? ??? ?e.printStackTrace();//输出异常信息
?? ??? ?}
?? ?
?? ?}
?? ?public void run(){//run方法
?? ??? ?while(true) {
?? ??? ??? ?DatagramPacket packet = null;//数据包
?? ??? ??? ?byte data[]=weather.getBytes();//字符串消息的字节数组
?? ??? ??? ?packet = ?new ?DatagramPacket(data,data.length,iaddress,port);//将数据打包
?? ??? ??? ?System.out.println(weather);//控制台打印消息
?? ??? ??? ?try {
?? ??? ??? ??? ?socket.send(packet);//发送数据
?? ??? ??? ??? ?sleep(3000);//让线程休眠3000毫秒
?? ??? ??? ?}catch(IOException e){
?? ??? ??? ??? ?e.printStackTrace();
?? ??? ??? ?}catch(InterruptedException e) {
?? ??? ??? ??? ?e.printStackTrace();
?? ??? ??? ?}
?? ??? ?}?? ?
?? ??? ??? ?}
?? ?public static void main(String[]args) {
?? ??? ?Notification w =new Notification();
?? ??? ?w.start();//启动线程
?? ?}
}接收类代码如下:package udp;
?
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.MulticastSocket;
?
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.WindowConstants;
//接收 ?后运行
public class Receive extends JFrame implements Runnable, ActionListener {
?? ?int port ;//端口
?? ?InetAddress group =null;//广播组地址
?? ?MulticastSocket socket = null;//多点广播套接字对象
?? ?JButton inceBtn = new JButton("开始接收");
?? ?JButton stopBtn = new JButton("停止接收");
?? ?JTextArea inceAr = new JTextArea(10,10);//显示接收广播的文本域
?? ?JTextArea inced = new JTextArea(10,10);
?? ?Thread thread ;
?? ?boolean stop = false;//定制接受信息状态
?? ?
?? ?public Receive () {
?? ??? ?setTitle("广播数据包");
?? ??? ?setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
?? ??? ?thread = new Thread(this);
?? ??? ?inceBtn.addActionListener(this);//绑定按钮ince的单击事件
?? ??? ?stopBtn.addActionListener(this);//绑定按钮stop的单击事件
?? ??? ?inceAr.setForeground(Color.blue);//指定文本域中文字的颜色
?? ??? ?
?? ??? ?JPanel north = new JPanel();
?? ??? ?north.add(inceBtn);//将按钮添加到面板north上
?? ??? ?north.add(stopBtn);
?? ??? ?add(north,BorderLayout.NORTH);//将north放置在窗体的上部
?? ??? ?JPanel center = new JPanel();//创建面板对象center
?? ??? ?center.setLayout(new GridLayout(1,2));//设置面板布局
?? ??? ?center.add(inceAr);//将文本域添加到面板上
?? ??? ?center.add(inced);
?? ??? ?add(center,BorderLayout.CENTER);//设置面板的布局
?? ??? ?validate();//刷新
?? ??? ?port =9898;//设置端口号
?? ??? ?try {
?? ??? ??? ?group = InetAddress.getByName("224.255.10.0");//指定接收地址
?? ??? ??? ?socket = new MulticastSocket(port);//绑定多点广播套接字
?? ??? ??? ?socket.joinGroup(group);//加入广播组
?? ??? ?}catch(IOException e){
?? ??? ??? ?e.printStackTrace();//输出异常信息
?? ??? ?}
?? ??? ?setBounds(100,50,360,380);//设置布局
?? ??? ?setVisible(true);//将窗体设置为显示状态
?? ?}
?? ?public void run() {//run方法
?? ??? ?while (!stop) {
?? ??? ??? ?byte data[] = new byte[1024];//创建缓存字节数组
?? ??? ??? ?DatagramPacket packet = null;
?? ??? ??? ?packet = new ?DatagramPacket(data,data.length,group,port);//待接收的数据包
?? ??? ??? ?try {
?? ??? ??? ??? ?socket.receive(packet);//接收数据包
?? ??? ??? ??? ?//获取数据包中的内容
?? ??? ??? ??? ?String message ?= new String(packet.getData(),0,packet.getLength());
?? ??? ??? ??? ?inceAr.setText("正在接收的内容:\n"+message);//将接受内容显示在文本域中
?? ??? ??? ??? ?inced.append(message+"\n");//每条信息为一行
?? ??? ??? ?}catch(IOException e ) {
?? ??? ??? ??? ?e.printStackTrace();//输出异常信息
?? ??? ??? ?}
?? ??? ??? ?
?? ??? ?}
?? ?}
?? ?public void actionPerformed(ActionEvent e) {//单机按钮ince出发时间
?? ??? ?if(e.getSource()==inceBtn) {
?? ??? ??? ?inceBtn.setBackground(Color.red);//设置按钮颜色
?? ??? ??? ?stopBtn.setBackground(Color.yellow);
?? ??? ??? ?if(!(thread.isAlive())) {//如线程不处于“新建状态”
?? ??? ??? ??? ?thread = new Thread(this);//实例化Thread对象
?? ??? ??? ?}
?? ??? ??? ?thread.start();//启动线程
?? ??? ??? ?stop = false;//开始接受信息
?? ??? ?}
?? ??? ?if(e.getSource()== stopBtn) {//单机按钮stop出发时间
?? ??? ??? ?inceBtn.setBackground(Color.yellow);//设置按钮亚瑟
?? ??? ??? ?stopBtn.setBackground(Color.red);
?? ??? ??? ?stop = true;//停止接收信息
?? ??? ?}
?? ?}
?? ?public static void main(String[]args) {
?? ??? ?Receive rec = new Receive();
?? ??? ?rec.setSize(460,200);
?? ?}
}

接收类代码如下:

 
  1. package udp;
    ?
    import java.awt.BorderLayout;
    import java.awt.Color;
    import java.awt.GridLayout;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.io.IOException;
    import java.net.DatagramPacket;
    import java.net.InetAddress;
    import java.net.MulticastSocket;
    ?
    import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.JTextArea;
    import javax.swing.WindowConstants;
    //接收 ?后运行
    public class Receive extends JFrame implements Runnable, ActionListener {
    ?? ?int port ;//端口
    ?? ?InetAddress group =null;//广播组地址
    ?? ?MulticastSocket socket = null;//多点广播套接字对象
    ?? ?JButton inceBtn = new JButton("开始接收");
    ?? ?JButton stopBtn = new JButton("停止接收");
    ?? ?JTextArea inceAr = new JTextArea(10,10);//显示接收广播的文本域
    ?? ?JTextArea inced = new JTextArea(10,10);
    ?? ?Thread thread ;
    ?? ?boolean stop = false;//定制接受信息状态
    ?? ?
    ?? ?public Receive () {
    ?? ??? ?setTitle("广播数据包");
    ?? ??? ?setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    ?? ??? ?thread = new Thread(this);
    ?? ??? ?inceBtn.addActionListener(this);//绑定按钮ince的单击事件
    ?? ??? ?stopBtn.addActionListener(this);//绑定按钮stop的单击事件
    ?? ??? ?inceAr.setForeground(Color.blue);//指定文本域中文字的颜色
    ?? ??? ?
    ?? ??? ?JPanel north = new JPanel();
    ?? ??? ?north.add(inceBtn);//将按钮添加到面板north上
    ?? ??? ?north.add(stopBtn);
    ?? ??? ?add(north,BorderLayout.NORTH);//将north放置在窗体的上部
    ?? ??? ?JPanel center = new JPanel();//创建面板对象center
    ?? ??? ?center.setLayout(new GridLayout(1,2));//设置面板布局
    ?? ??? ?center.add(inceAr);//将文本域添加到面板上
    ?? ??? ?center.add(inced);
    ?? ??? ?add(center,BorderLayout.CENTER);//设置面板的布局
    ?? ??? ?validate();//刷新
    ?? ??? ?port =9898;//设置端口号
    ?? ??? ?try {
    ?? ??? ??? ?group = InetAddress.getByName("224.255.10.0");//指定接收地址
    ?? ??? ??? ?socket = new MulticastSocket(port);//绑定多点广播套接字
    ?? ??? ??? ?socket.joinGroup(group);//加入广播组
    ?? ??? ?}catch(IOException e){
    ?? ??? ??? ?e.printStackTrace();//输出异常信息
    ?? ??? ?}
    ?? ??? ?setBounds(100,50,360,380);//设置布局
    ?? ??? ?setVisible(true);//将窗体设置为显示状态
    ?? ?}
    ?? ?public void run() {//run方法
    ?? ??? ?while (!stop) {
    ?? ??? ??? ?byte data[] = new byte[1024];//创建缓存字节数组
    ?? ??? ??? ?DatagramPacket packet = null;
    ?? ??? ??? ?packet = new ?DatagramPacket(data,data.length,group,port);//待接收的数据包
    ?? ??? ??? ?try {
    ?? ??? ??? ??? ?socket.receive(packet);//接收数据包
    ?? ??? ??? ??? ?//获取数据包中的内容
    ?? ??? ??? ??? ?String message ?= new String(packet.getData(),0,packet.getLength());
    ?? ??? ??? ??? ?inceAr.setText("正在接收的内容:\n"+message);//将接受内容显示在文本域中
    ?? ??? ??? ??? ?inced.append(message+"\n");//每条信息为一行
    ?? ??? ??? ?}catch(IOException e ) {
    ?? ??? ??? ??? ?e.printStackTrace();//输出异常信息
    ?? ??? ??? ?}
    ?? ??? ??? ?
    ?? ??? ?}
    ?? ?}
    ?? ?public void actionPerformed(ActionEvent e) {//单机按钮ince出发时间
    ?? ??? ?if(e.getSource()==inceBtn) {
    ?? ??? ??? ?inceBtn.setBackground(Color.red);//设置按钮颜色
    ?? ??? ??? ?stopBtn.setBackground(Color.yellow);
    ?? ??? ??? ?if(!(thread.isAlive())) {//如线程不处于“新建状态”
    ?? ??? ??? ??? ?thread = new Thread(this);//实例化Thread对象
    ?? ??? ??? ?}
    ?? ??? ??? ?thread.start();//启动线程
    ?? ??? ??? ?stop = false;//开始接受信息
    ?? ??? ?}
    ?? ??? ?if(e.getSource()== stopBtn) {//单机按钮stop出发时间
    ?? ??? ??? ?inceBtn.setBackground(Color.yellow);//设置按钮亚瑟
    ?? ??? ??? ?stopBtn.setBackground(Color.red);
    ?? ??? ??? ?stop = true;//停止接收信息
    ?? ??? ?}
    ?? ?}
    ?? ?public static void main(String[]args) {
    ?? ??? ?Receive rec = new Receive();
    ?? ??? ?rec.setSize(460,200);
    ?? ?}
    }代码图如下所示:
  2. 运行结果如下所示:


?

文章来源:https://blog.csdn.net/2302_76551984/article/details/135213214
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。