Java🎯网络通信
|字数总计:3.5k|阅读时长:13分钟|阅读量:
网络通信
相关概念
网络
(1) 概念:连接终端系统(主机)的通信系统
。
(2) 功能:实现资源共享、通信
。
- 局域网(Local Area Network,LAN),就是同一区域内通过一定形式连接起来的计算机。
- 广域网(Wide Area Network,WAN),由LAN延伸到更大的范围。
- 因特网(Internet),由无数的LAN和WAN组成。
服务器
是指提供信息的计算机或程序
,客户机
是指请求信息的计算机或程序
,而网络用于连接服务器与客户机,实现两者相互通信。
IP地址
:IP地址是计算机在互联网中唯一标识
。
端口
:区分应用程序
,实现程序间的通信
- 假如一台计算机提供了HTTP、FTP等多种服务,那么客户机通过
不同的端口
来确定连接到服务器的哪项服务上。
说明: 0~1023端口用于知名网络服务和应用,1024以上的端口用于用户的普通应用程序。

套接字(Socket)
(1)功能:连接应用程序
和端口(Port)
。
(2) 客户端与服务器通过套接字
建立连接
和通信
:
① UDP套接字
:不可靠。
② TCP/IP套接字
:
- 可靠的双向流协议;
- 可发送任意数量的数据;
- 提供消息确认、错误检测、错误恢复等服务。
Java将套接字抽象化为类,程序设计者只需创建Socket类对象,即可使用套接字。

C/S模式
客户端/服务器模式(c/s)
①客户端:请求服务
的计算机。
②服务器:提供服务
的计算机。
- 多个客户端可
同时访问
服务器。
- 一台服务器可以
同时
为数千台客户端服务
。


java.net包
(1) InetAddress类
-
封装IP地址
,提供与IP地址相关的方法。
- InetAddress方法会抛出
UnknownHostException
异常,在主机不存在
或网络连接错误
时发生。
InetAddress类常用方法 |
说明 |
InetAddress getLocalHost( ) |
创建本地主机的InetAddress对象(含主机名+IP地址) |
String getHostName( ) |
如果是本机则返回计算机名,不是本机则返回主机名,没有域名则是IP地址。 |
String getHostAddress( ) |
返回IP地址 |
InetAddress getByName( String host) |
已知主机名,返回主机的InetAddress对象 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| package net; import java.net.*; public class LoaclIPTest {
public static void main(String[] args) { InetAddress ip; try { ip=InetAddress.getLocalHost(); String localname=ip.getHostName(); String localip=ip.getHostAddress(); System.out.println("本机名:" + localname); System.out.println("本机IP地址:" + localip); System.out.println("本机InetAddress对象:" + ip);
}catch(UnknownHostException e) { e.printStackTrace(); } }
}
|
(2) ServerSocket
- 用于创建TCP
服务器端
Socket,使服务器绑定一个端口,等待客户的连接请求。
ServerSocket常用方法 |
说明 |
构造方法:ServerSocket(int port) |
创建绑定到特定端口的服务器套接字 |
Socket accept() |
等待客户端的连接,有客户端连接会返回一个对应的Socket |
InetAddress getInetAddress() |
返回封装了ServerSocket绑定的IP地址的InetAddress对象 |
boolean isClosed() |
判断ServerSocket是否关闭 |
void bind(SocketAddress endpoint) |
将ServerSocket对象绑定到指定的IP地址和端口号 |
int getInetAddress() |
返回服务器套接字等待的端口号 |
void close() |
关闭套接字 |
boolean isBound() |
判断ServerSocket的绑定状态 |
(3) Socket
Socket常用方法 |
说明 |
Socket(String hostName,int port) |
根据主机名和端口创建Socket |
Socket(InetAddress a,int port) |
根据InetAddress和端口创建Socket |
InputStream getInputStream() |
返回InputStream类型的输入流对象 |
OutputStream getOutputStream() |
返回OutputStream类型的输出流对象 |
int getPort() |
返回Socket对象与服务器端连接端口号 |
InetAddress getLocalAddress() |
获取Socket对象绑定的本地IP地址 |
void close() |
关闭Socket连接,结束本次通信 |
编写C/S程序
服务器端
创建
一个服务器套接字
(ServerSocket),绑定到指定的端口
。
- 调用
accept()
方法,侦听
来自客户端的请求
,如果客户发出请求,则接受
连接,返回
通信套接字(Socket)。
- 调用Socket的
getInputStream
和getOutpuStream
方法,获得I/O流
,开始网络数据的接收
和发送
。
- 关闭
通信套接字
,关闭服务器套接字
。
客户端
创建
一个套接字
(Socket),向服务器的侦听端口发出请求。
- 与服务器正确连接后,调用
Socket类
的getInputStream()
和getOutputStream()
方法,获得I/O流,开始网络数据的接收和发送。
- 关闭
通信套接字
。

Socket通信方式
利用Socket方式进行数据通信与传输的整个过程如图所示:Socket
对象代表主叫方
,ServerSocket
对象代表被叫方
,执行accept()
方法表示同意建立连接
。连接一旦建立,会自动创建一个输入流和一个输出流,通过这两个流可以实现数据的发送。

Socket编程思路
(1)I/O流
- 计算机系统将除
CPU
、内存以外
的其他设备
都当作文件
处理,包括网络终端(网卡)也不例外。
- 两台主机之间通过Socket建立握手连接之后,主要通过
I/O流
来接收
和发送
数据,实际上,绝大部分网络操作是在操作I/O流
。
- 操作
网络端口流
与操作磁盘文件流
原理相似。
- 出于效率的考虑,
Socket
使用的是字节流
,但是在实际操作中,字节往往会带来不便,所以我们一般会把字节流
改造成字符流
后进行操作。
(2)输入
- 先利用
InputStreamReader
将InputStream
转化成字符流
- 然后再使用
BufferedReader
建立缓冲区,以提高效率。1 2 3 4 5
| InputStream is=socket.getInputStream(); InputStreamReader isr=new InputStreamReader(is); BufferedReader in=new BufferedReader(isr); in.readLine();
|
(3)输出
- 利用
PrintWriter
类对OutputStream
进行包装
PrintWriter
称为打印输出流,包装类,它可以直接输出各种类型的数据。
如:void println( String ) ;1 2 3
| OutputStream os=socket.getOutputStream(); PrintWriter pw=new PrintWriter(os, true); pw.println(“待写信息”);
|
C/S实例
Client客户端
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
| package 网络通信; import java.io.*; import java.net.*; import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; public class Client implements ActionListener { JFrame f; JPanel p; JTextArea jt; JTextField t; JButton b; JScrollPane jsp; PrintWriter pw; public Client() { f=new JFrame("客户端窗口"); p=new JPanel(); jt=new JTextArea(); t=new JTextField(20); b=new JButton("发送"); b.addActionListener(this); f.add(p); p.add(jt); p.add(t); p.add(b); jsp=new JScrollPane(jt); f.add(jsp); f.setSize(350,250); f.setLocation(300, 200); f.add(p,BorderLayout.SOUTH); f.setIconImage((new ImageIcon("MyImage/qq图标.jpg")).getImage()); f.setResizable(false); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true); try { Socket s=new Socket("127.0.0.1",8998); pw=new PrintWriter(s.getOutputStream(),true); InputStreamReader isr=new InputStreamReader(System.in); BufferedReader br=new BufferedReader(isr); InputStreamReader isr1=new InputStreamReader(s.getInputStream()); BufferedReader br1=new BufferedReader(isr1); while(true) {
String str1=br1.readLine(); jt.append("服务器对我说说:"+str1+"\r\n"); } }catch(Exception e) { e.printStackTrace(); } } public static void main(String[] args) { Client c=new Client(); new Client(); } @Override public void actionPerformed(ActionEvent e) { if(e.getSource()==b) { String str=t.getText(); jt.append("我对服务器说:"+str+"\r\n"); pw.println(str); t.setText(""); } } }
|
Server服务端
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
| package 网络通信; import java.net.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener;
import javax.swing.*; import java.io.*; public class Server implements ActionListener { JFrame f; JPanel p; JTextArea jt; JTextField t; JButton b; JScrollPane jsp; PrintWriter pw; public Server(){ f=new JFrame("服务器窗口"); p=new JPanel(); jt=new JTextArea(); t=new JTextField(20); b=new JButton("发送"); b.addActionListener(this); f.add(p); p.add(jt); p.add(t); p.add(b); jsp=new JScrollPane(jt); f.add(jsp); f.setSize(350,250); f.setLocation(300, 600); f.add(p,BorderLayout.SOUTH); f.setIconImage(new ImageIcon("MyImage/qq图标.jpg").getImage()); f.setResizable(false); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
try { ServerSocket ss=new ServerSocket(8998); System.out.println("服务器正在监听"); Socket so=ss.accept(); InputStreamReader isr=new InputStreamReader(so.getInputStream()); BufferedReader br=new BufferedReader(isr); pw = new PrintWriter(so.getOutputStream(),true);
while(true) { String str=br.readLine(); jt.append("客户端对我说说:"+str+"\r\n");
} }catch(Exception e) { e.printStackTrace(); } } public static void main(String[] args) { Server s=new Server(); new Server(); } @Override public void actionPerformed(ActionEvent e) { if(e.getSource()==b) { String str=t.getText(); jt.append("我对客户端说:"+str+"\r\n"); pw.println(str); t.setText(""); } }
}
|
