Java第十八章-网络通信
程序员文章站
2023-12-23 19:01:45
...
绪论
通过计算机网络,相互连接的计算机彼此之间可以进行数据交流,如要编写网络应用程序,首先要明确这些应用程序所使用的网络协议。
局域网与因特网
//服务器是指提供信息的计算机或是应用程序
//客户机是指请求信息的计算机或是程序
//局域网(LAN)是指一群通过一定形式连接起来的计算机
//有LAN延伸到更大的范围,称为广域网(WAN)
//我们熟知的因特网,有无数的LAN和WAN组成
网络协议
IP协议
//因特网采用的时TCP/IP协议,因特网上有数千上万个主机,每一个主机分配一个地址即为IP地址。目前IP地址由四个字节组成即32位二进制数称为IPv4,通常取每个字节的十进制数且每个字节有一个点做分隔符,例如:192.168.1.1
//TCP/IP模式是一种层次结构共分为4层。应用层、传输层、互联网层、网络层,各层功能有一定的独立性。
TCP与UDP协议
//TCP:传输控制协议
//UDP:用户数据报协议
//TCP协议时一种以固接连接为基础的协议,可以保证数据准确达到,而且抵达的数据排列顺序与输送时相同,应用一些可靠性要求比较高的场所
//UDP协议无连接通信协议,不保证数据的可靠性。而且无法保证顺序,应用一些数据准确性要求不是很高的场所。
端口和套接字
//一班而言,一台计算机只有单一的连接到网络的物理连接,所有的数据都通过此连接对内外送达指定的计算机,这就是端口(port)。网络程序的端口并非真实存在。端口范围0~65535之间的整数HTTP使用80端口,FTP使用21端口。
//0~1023之间的端口用于一些知名的网络服务程序。普通用户选取1024以上。
//网络程序中的套接字(Socket)用于将应用程序与端口连接起来。
TCP程序设计基础
//利用TCP进行·通信的俩个程序具有主次之分,一个称为服务器程序,另一个称为客户机程序。
InetAddress类
//此类是与IP地址相关的类,利用该类可以获取IP地址、主机地址等信息。
package 网络通信;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.UnknownHostException;
public class Address {
public static void main(String args[]) {
//创建InetAddress类对象
InetAddress ip;
try {
//实例化该类对象
ip = InetAddress.getLocalHost();
//获取本机名与IP地址
String localname = ip.getHostName();
String loacalip = ip.getHostAddress();
System.out.println("本机名" + localname);
System.out.println("本机IP地址" + loacalip);
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
}
ServerSocket类
//此类表示服务器套接字,其主要功能是等待来自网络的请求。它也可以通过指定的端口来等待连接的套接字。
TCP网络程序
//单向通信:只要求客户机向服务器发送消息,不要求服务器向客户机发送消息。
//简单单向通信f服务端程序案例:
package 网络通信;
import 输入输出.MyZip;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
public class MyTcp {
//创建BufferedReader类对象
private BufferedReader reader;
//创建ServerSocket类对象
private ServerSocket serverSocket;
//创建Socket对象
private Socket socket;
void getserver() {
try {
//实例化ServerSocket类对象
serverSocket = new ServerSocket(8998);
System.out.println("服务器套接字已创建成功");
//如果套接字是连续状态的
while (true) {
System.out.println("等待客户机的连接");
//实例化Socket类对象
socket = serverSocket.accept();
reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
getClientMessage();
}
} catch (Exception e) {
e.printStackTrace();
}
}
private void getClientMessage() {
try {
//如果客户机是连接状态
while (true) {
//获取客户信息
System.out.println("客户机" + reader.readLine());
}
} catch (Exception e) {
e.printStackTrace();
}
try {
//关闭流和套接字
if (reader != null) {
reader.close();
}
if (socket != null) {
socket.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String args[]) {
//实例化本类对象
MyTcp myTcp = new MyTcp();
myTcp.getserver();
}
}
//客户端案例,实现将用户在文本框中输入的信息发送至服务器,将文本框中的输入的信息显示在客户端的文本域中
package 网络通信;
import javax.swing.*;
import javax.swing.border.BevelBorder;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.PrintWriter;
import java.net.Socket;
public class MyClient extends JFrame {
//声明各类对象
private PrintWriter printWriter;
Socket socket;
private JTextArea jTextArea = new JTextArea();
private JTextField jTextField = new JTextField();
Container cc;
public MyClient(String title) {
//调用父类构造方法
super(title);
//实例化对象
cc = this.getContentPane();
final JScrollPane jScrollPane = new JScrollPane();
jScrollPane.setBorder(new BevelBorder(BevelBorder.RAISED));
getContentPane().add(jScrollPane,BorderLayout.CENTER);
jScrollPane.setViewportView(jTextArea);
//将文本框放在窗体的最下部
cc.add(jTextField,"South");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jTextField.addActionListener(new ActionListener() {
//绑定事件
public void actionPerformed(ActionEvent e) {
//将本文框的信息写入流
printWriter.println(jTextField.getText());
//将文本框的信息显示在文本域中
jTextArea.append(jTextField.getText() + "\n");
jTextArea.setSelectionEnd(jTextArea.getText().length());
//将文本框清空
jTextField.setText("");
}
});
}
//连接套接字的方法
private void connect() {
//文本域中提示信息
jTextArea.append("尝试连接\n");
try {
//实例化Socket类对象
socket = new Socket("127.0.0.1",8998);
printWriter = new PrintWriter(socket.getOutputStream(),true);
//文本域中提示信息
jTextArea.append("完成连接\n");
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String args[]) {
MyClient myClient = new MyClient("向服务器送数据");
myClient.setSize(200,200);
myClient.setVisible(true);
myClient.connect();
}
}
UDP程序设计
//用户数据报协议传输信息更快,但不提供可靠的保证。
//主机不断地播出天气预报,可以保证加入到同一组的主机随时可接收到广播信息。接受这将正在接收的信息放在一个文本域中,并将接受的全部信息放入另一个文本域中
package 网络通信;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.MulticastSocket;
public class Weather extends Thread{
String weather = "节目预报:八点有大型晚会,请收听";
//定义端口
int port = 9898;
//创建InetAddress类对象
InetAddress inetAddress = null;
//声明多点广播套接字
MulticastSocket socket = null;
Weather() {
try {
//实例化InetAddress,指定地址
inetAddress = InetAddress.getByName("224.255.10.0");
//实例化多点字广播套接字
socket = new MulticastSocket(port);
//指定发送范围的本地网络
socket.setTimeToLive(1);
//加入广播组
socket.joinGroup(inetAddress);
} catch (Exception e) {
e.printStackTrace();
}
}
public void run() {
while (true) {
//声明DatagramPacket对象
DatagramPacket packet = null;
//声明字节数
byte[] data = weather.getBytes();
//将数据包打印
packet = new DatagramPacket(data, data.length, inetAddress, port);
//将广播信息输出
System.out.println(new String(data));
try {
//发送数据
socket.send(packet);
sleep(3000);
} catch (Exception e) {
e.printStackTrace();
}
}
}
public static void main(String args[]) {
Weather w = new Weather();
w.start();
}
}
//单击开始接收按钮,系统开始接收主机播出的信息,停止接收按钮则停止接收
package 网络通信;
import javafx.scene.layout.BorderRepeat;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.MulticastSocket;
public class Receive extends JFrame implements Runnable, ActionListener {
int port;
InetAddress group = null;
//创建多点广播套接字对象
MulticastSocket socket = null;
//创建按钮对象
JButton ince = new JButton("开始接收");
JButton stop = new JButton("停止接收");
//显示接收广播的文本域
JTextArea inceAr = new JTextArea(10,10);
JTextArea inced = new JTextArea(10,10);
//创建Thread对象
Thread thread;
//创建boolean类型变量
boolean b = false;
public Receive() {
//调用父类方法
super("广播数据报");
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
thread = new Thread(this);
//绑定ince按钮的单击事件
ince.addActionListener(this);
//绑定stop按钮的单击事件
stop.addActionListener(this);
//指定文本域中文字颜色
inceAr.setForeground(Color.blue);
//创建Jpanel对象
JPanel north = new JPanel();
//将按钮添加到面板上
north.add(ince);
north.add(stop);
//将north放在窗体上部
add(north,BorderLayout.NORTH);
JPanel center = new JPanel();
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 (Exception e) {
e.printStackTrace();
}
setBounds(100,50,360,380);
setVisible(true);
}
public void run() {
while (true) {
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.setText(message + "\n");
} catch (Exception e) {
e.printStackTrace();
}
if (b == true) {
break;
}
}
}
//点击事件
public void actionPerformed(ActionEvent e) {
//单击按钮ince触发的事件
if (e.getSource() == ince) {
//设置颜色按钮
ince.setBackground(Color.red);
stop.setBackground(Color.black);
//如果线程不处于“新建状态”
if (!(thread.isAlive())) {
thread = new Thread(this);
}
thread.start();
b = false;
}
//单击按钮stop触发的事件
if (e.getSource() == stop) {
//设置按钮颜色
ince.setBackground(Color.yellow);
stop.setBackground(Color.red);
b = true;
}
}
public static void main(String args[]) {
Receive rec = new Receive();
rec.setSize(460,200);
}
}