第二十一章总结。。

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

网络程序设计基础:

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

Internet 提供了大量有用的信息,很少有人能在接触过Internet后拒绝它的诱惑。计算机网络实现了多台计算机间的互联,使得它们彼此之间能够进行数据交流。网络应用程序就是在已连接的不同计算机上运行的程序,这些程序借助于网络协议,相互之间可以交换数据。编写网络应用程序前,首先必须明确所要使用的网络协议。

21.1网络程序设计基础

网络程序设计编写的是与其他计算机进行通信的程序。Java已经将网络程序所需要的元素封装或不同的类,用户只要创建这些类的对象,使用相应的方法,即使不具备有关的网络知识,也可以编写出高质量的网络通信程序。

1.1局域网与互联网

为了实现两台计算机的通信,必须用一个网络线路连接两台计算机。

1.2网络协议

网络协议规定了计算机之间连接的物理、机械(网线与网卡的连接规定)、电气(有效的电平范围)等特征,计算机之间的相互寻址规则,数据发送冲突的解决方式,长数据如何分段传送与接收等内容。就像不同的国家有不同的法律一样,目前网络协议也有多种。下面简单地介绍几个常用的网络协议。

(1)IP 协议

IP 是Internet Protocol的简称,是一种网络协议。Internet网络采用的协议是TCP/IP协议,其全称是Transmission Control Protocol/Internet Protocol。Internet依靠TCP/IP协议,在全球范围内实现了不同硬件结构、不同操作系统、不同网络系统间的互联。在Internet网络上存在着数以亿计的主机,每台主机都用网络为其分配的Internet地址代表自己,这个地址就是IP地址。

(2)TCP与UDP 协议

在TCP/IP协议栈中,有两个高级协议是网络应用程序编写者应该了解的,即传输控制协议(Transmission Control Protocol,TCP)与用户数据报协议(User Datagram Protocol,UDP)。

TCP协议是一种以固接连线为基础的协议,它提供两台计算机间可靠的数据传送。TCP可以保证数据从一端送至连接的另一端时,能够确实送达,而且抵达的数据的排列顺序和送出时的顺序相同。因此,TCP协议适合可靠性要求比较高的场合。就像拨打电话,必须先拨号给对方,等两端确定连接后,相互才能听到对方说话,也知道对方回应的是什么。

HTTP、FTP 和 Telnet等都需要使用可靠的通信频道。例如,HTTP从某个URL读取数据时,如果收到的数据顺序与发送时不相同,可能就会出现一个混乱的HTML文件或是一些无效的信息。

UDP是无连接通信协议,不保证数据的可靠传输,但能够向若干个目标发送数据,或接收来自若干个源的数据。UDP以独立发送数据包的方式进行。这种方式就像邮递员送信给收信人,可以寄出很多信给同一个人,且每一封信都是相对独立的,各封信送达的顺序并不重要,收信人接收信件的顺序也不能保证与寄出信件的顺序相同。

UDP协议适合于一些对数据准确性要求不高,但对传输速度和时效性要求非常高的网站,如网络聊天室、在线影片等。这是由于TCP协议在认证上存在额外耗费,可能使传输速度减慢,而UDP协议即使有一小部分数据包遗失或传送顺序有所不同,也不会严重危害该项通信。

注意

一些防火墙和路由器会设置成不允许UDP数据包传输,因此若遇到UDP连接方面的问题,应先确定所在网络是否允许UDP协议。

1.3 端口与套接字

一般而言,一台计算机只有单一的连到网络的物理连接(PhysicalConnection),所有的数据都通过此连接对内、对外送达特定的计算机,这就是端口。网络程序设计中的端口(port)并非真实的物理存在,而是一个假想的连接装置。端口被规定为一个在0~65535的整数。HTTP服务一般使用80端口, FTP服务使用21端口。假如一台计算机提供了HTTP、FTP等多种服务,那么客户机会通过不同的端口来确定连接到服务器的哪项服务上,如图21.3所示。

通常,0~1023 的端口数用于一些知名的网络服务和应用,用户的普通网络应用程序应该使用1024以上的端口数,以避免端口号与另一个应用或系统服务所用端口冲突。

网络程序中的套接字(Socket)用于将应用程序与端口连接起来。套接字是一个假想的连接装置,就像插座一样可连接电器与电线,如图21.4所示。Java将套接字抽象化为类,程序设计者只需创建Socket类对象,即可使用套接字。

21.2 TCP程序

TCP 网络程序设计是指利用Socket类编写通信程序。利用TCP协议进行通信的两个应用程序是有主次之分的,一个称为服务器程序,另一个称为客户机程序,两者的功能和编写方法大不一样。

2.1 InetAddress类

jae包中的InetAddress类是与IP地址相关的类,利用该类可以获取IP地址、主机地址等信息。

import java.net.InetAddress;

import java.rmi.UnknownHostException;

public class Address {

public static void main(String[] args) throws UnknownHostException {

InetAddress l = null;

InetAddress ip = l;

try {

ip = InetAddress.getLocalHost();

} catch (java.net.UnknownHostException e) {

e.printStackTrace();

}

String localname = ip.getHostName();

String localip = ip.getHostAddress();

System.out.println("本机名: " + localname);

System.out.println("本机IP地址: "+ localip);

}

}

2.2 ServerSocket 类

java.net包中的ServerSocket类用于表示服务器套接字,其主要功能是等待来自网络上的"请求"。

它可通过指定的端口来等待连接的套接字。服务器套接字一次可以与一个套接字连接。如果多台客户机同时提出连接请求,服务器套接字会将请求连接的客户机存入列队中,然后从中取出一个套字。与服务器新建的套接字连接起来。若请求连接数大于最大容纳数,则多出的连接请求被拒绝。默认大小是50。

2.3TCP通信

TCP通信方式呢 主要的通讯方式是一对一的通讯方式,也有着优点和缺点 它的优点对比于UDP来说就是更可靠 因为它的通讯方式是需要先发送消息 看看客户端是否能够接收到消息 如果没有回复消息的话 服务端 就不会发出文件 等待客户端回复消息,这个握手模式的话 就会非常可靠 以下代码进行讲解:

21.3UDP程序

用户数据报协议(UDP)是网络信息传输的另一种形式。基于UDP的通信和基于TCP的通信不同,基于UDP的信息传递更快,但不提供可靠性保证。使用UDP传递数据时,用户无法知道数据能否正确地到达主机,也不能确定到达目的地的顺序是否和发送的顺序相同。虽然UDP是一种不可靠的协议,但如果需要较快地传输信息,并能容忍小的错误,可以考虑使用UDP。

基于 UDP通信的基本模式如下:

☑将数据打包(称为数据包),然后将数据包发往目的地。

☑接收别人发来的数据包,然后查看数据包。

发送数据包的步骤如下:

(1)使用DatagramSocket()创建一个数据包套接字。

(2)使用DatagramPacket(byte[] buf, int offset, int length, InetAddress address, int port)创建要发的数据包。

(3)使用DatagramSocket类的send()方法发送数据包。

接收数据包的步骤如下:

(1)使用DatagramSocket(int port)创建数据包套接字,绑定到指定的端口。

(2)使用DatagramPacket(byte[] buf, int length)创建字节数组来接收数据包。

(3)使用DatagramPacket类的receive(方法接收UDP包。

注意

DatagramSocket类的receive()方法接收数据时,如果还没有可以接收的数据,在正常情况下 receive()方法将阻害,一直等到网络上有数据传来,receive()方法接收该数据并返回。如果网络上没有数据发送过来,receive()方法也没有阻塞,肯定是程序有问题,大多数情况下是因为使用了一个被其他程序占用的端口号。

3.1 DatagramPacket类

javanet 包的 DatagramPacket类用来表示数据包。DatagramPacket类的构造方法如下:☑DatagramPacke1(byte]buf, int length).

DatagramPackel(byse[] buf,int length,InetAddress address, int port).

第一种构造方法在创建DatagramPacket对象时,指定了数据包的内存空间和大小。第二种构造方法不仅指定了数据包的内存空间和大小,还指定了数据包的目标地址和端口。在发送数据时,必须指定接收方的Socket地址和端口号,因此使用第二种构造方法可创建发送数据的DatagramPacket对象。

3.2 DatagramSocket 类

java.net 包中的DatagramSocket类用于表示发送和接收数据包的套接字。该类的构造方法如下:☑DatagramSocket()。

☑DatagramSocket(int port)。

DatagramSocket(int port, InetAddress addr)。

第一种构造方法创建DatagramSocket对象,构造数据报套接字,并将其绑定到本地主机任何可用的端口上。第二种构造方法创建DatagramSocket对象,创建数据报套接字,并将其绑定到本地主机的指定端口上。第三种构造方法创建DatagramSocket对象,创建数据报套接字,并将其绑定到指定的端口和指定的本地地址上。第三种构造函数适用于有多块网卡和多个IP地址的情况。

最主要的是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、端口为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程序跟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);

}

}

相关推荐
一只小青团39 分钟前
Python之面向对象和类
java·开发语言
qq_529835351 小时前
ThreadLocal内存泄漏 强引用vs弱引用
java·开发语言·jvm
落笔画忧愁e1 小时前
扣子Coze飞书多维表插件添加数据记录
java·服务器·飞书
秋千码途4 小时前
小架构step系列08:logback.xml的配置
xml·java·logback
飞翔的佩奇4 小时前
Java项目:基于SSM框架实现的旅游协会管理系统【ssm+B/S架构+源码+数据库+毕业论文】
java·数据库·mysql·毕业设计·ssm·旅游·jsp
时来天地皆同力.4 小时前
Java面试基础:概念
java·开发语言·jvm
找不到、了4 小时前
Spring的Bean原型模式下的使用
java·spring·原型模式
阿华的代码王国5 小时前
【Android】搭配安卓环境及设备连接
android·java
YuTaoShao5 小时前
【LeetCode 热题 100】141. 环形链表——快慢指针
java·算法·leetcode·链表
铲子Zzz6 小时前
Java使用接口AES进行加密+微信小程序接收解密
java·开发语言·微信小程序