网络编程

计算机网络

image.png

网络编程

在网络通信写一下,实现网络互联的不同计算机上运行的程序间可以进行数据交换

网络编程三要素

IP地址

IP地址是用来标记计算机设备
image.png

端口

端口是用来标记该IP地址计算机设备中的应用程序
image.png

协议

计算机与计算机链接和通信时需要遵循一定的规则,常见规则是TCP和UDP协议image.png

IP地址

IP地址: 是网络设备中的唯一标识
image.png
常用命令:

  1. - **ipconfig : 查看本机IP地址**
  2. - **ping IP地址: 检查网络是否连通**

特殊IP地址:

  1. - **127.0.0.1 测试使用**


InetAddress类

Java为了方便使用者对IP地址的获取和操作,提供了一个InetAddress类
InetAddress 类此类表示Internet协议(IP)地址
InetAddress类方法
static InetAddress getByName(String host) 确定主机名称的IP地址
String getHostAddress() 返回文本显示中的IP地址字符串
String getHostName() 获取此IP地址的主机名
代码实现:
public class InetAddressDemo {
_public static void main
(String[] args) throws UnknownHostException {
//static InetAddress getByName(String host) 确定主机名称的IP地址
InetAddress name = InetAddress._getByName(
“10.80.109.188”);
// String getHostName() 获取此IP地址的主机名。
String hostName = name.getHostName();
// String getHostAddress()返回文本显示中的IP地址字符串。
String hostAddress = name.getHostAddress();
System.out.println(“主机名: “ + hostName);
System.out.println(“IP地址: “ + hostAddress); }}

端口

端口: 设备室应用程序的唯一标识
image.png

协议

计算机与计算机链接和通信时需要遵循一定的规则,常见规则是TCP和UDP协议

UDP协议

  1. - **用户数据报协议(User Datagram Protocl)**
  2. - **大部分在音频,视频和普通数据中使用**

image.png

TCP协议

  1. - **传输控制协议(Transmission Control Protocl)**
  2. - **明确在客户端与服务器端,由客户端向服务端发出连接请求,三次握手**
  3. - **三次握手协议:TCP协议中,在发送数据的准备阶段,客户端与服务器之间的三次交互,以保证连接的可靠**
  4. - **第一次握手: 客户端向服务器端发出连接请求,等待服务器确认**
  5. - **第二次握手: 服务器向客户端回送一个响应,通知客户端收到了连接请求**
  6. - **第三次握手: 客户端再次向服务器端发送确认信息,确认连接**
  7. - **完成三次握手后,连接建立后,客户端和服务端就可以开始进行数据传输了。由于这种面向链接的特性,TCP协议可以保证传输数据的安全,所以应用十分广泛,例如:上传文件、下载文件、浏览网页等**

image.png

UDP协议通信原理

建立两个Socket对象,只是发送,接收数据
Java提供了DatagramSocket类-此类表示用于发送和接收数据报数据包的套接字
image.png

UDP发送数据

发送数据的步骤:

  1. 1. 创建发送端的Socket对象(DatagramSocket)
  2. 1. 创建数据,并把数据打包
  3. 1. 调用DatagramSocket对象的方法发送数据
  4. 1. 关闭发送端

public class UDPSendDemo {
_public static void main
(String[] args) throws IOException {
// 1.创建发送端的Socket对象(DatagramSocket)
// DatagramSocket() 构造数据报套接字并将其绑定到本地主机上的任何可用端口。
DatagramSocket dgs = new DatagramSocket
();
// 创建数据,并把数据打包
// 使用DatagramPacket类 — 该类表示数据报包
// 2. DatagramPacket(byte[] buf, int length, InetAddress address, int port)
// 构造用于发送长度的分组的数据报包 length指定主机上到指定的端口号
// 定义一个字节数组byte[] buf,将字节数组定义,并且使用getBytes获取该数组字节
byte
[] bytes = “hello,world”.getBytes();
// 获取字节长度int length
// int length = bytes.length;
// InetAddress address
// InetAddress address = InetAddress.getByName(“127.0.0.1”);
// int port
// int port = 8081;
// DatagramPacket p = new DatagramPacket(bytes, length, address, port);
// 简化代码写法
DatagramPacket dp = new DatagramPacket
(bytes, bytes.length, InetAddress.getByName(“127.0.0.1”), 8081);
// 调用DatagramSocket对象的方法发送数据
// send(DatagramPacket p) 从此套接字发送数据报包
// DatagramPacket类 — 该类表示数据报包
dgs.send
(dp);
// 关闭发送端,使用close()方法关闭
dgs.close
(); }}_

UDP接受数据

接受数据的步骤

  1. 1. 创建接收端的Socket对象(DatagramSocket)
  2. 1. 创建一个数据包,用于接收数据
  3. 1. 调用DategramSocket对象的方法接收数据
  4. 1. 解析数据包,并把数据在控制台显示
  5. 1. 关闭接收端

代码实现
public class ServiceDemo {
_public static void main
(String[] args) throws IOException {
// 创建接收端Socket对象(DatagramSocket)
// 使用DatagramSocket(int port)带参构造数据报套接字并绑定端口

DatagramSocket ds = new DatagramSocket
(8081);
// 创建一个数据包,用于接收数据
// DatagramPacket(byte[] buf, int length)
// 构造一个 DatagramPacket用于接收长度的数据包 length

byte
[] bytes = new byte[1024];
// 将定义接收的字节长度,以及字节对象传入到接收对象DatagranPacket中
DatagramPacket dp = new DatagramPacket
(bytes, bytes.length);
// 调用DatagramSocket对象的方法接收数据中的receive()方法传送对象数据
ds.receive
(dp);

// 解析数据包,并把数据在控制台显示
// byte[] getData() 返回数据缓冲区
// 使用getData()得到一个字节数组
/ byte[] data = dp.getData();
// 因为定义了一个接收字符串数组的长度为1024,收到数据会出现空数据
// int getLength() 返回要发送的数据的长度或接收到的数据的长度。
int length = dp.getLength();
// 因为需要显示在控制台,使用字符串转换方便查看,添加获取字节的长度
String sd = new String(data,0,length);
System.out.println(“获得数据是: “ + sd);
/


// 优化代码
System._out
.println(“获得数据是: “ + new String(_dp.getData(),0,dp.getLength()));
// 关闭接收端
ds.close
(); } }_

UDP通讯程序练习

按照下面需求实现程序

  1. - UCP发送数据: 数据来源键盘录入, 知道输入的数据是886,发送数据结束
  2. - UDP接收数据: 因为接收端不知道发送端什么时候停止发送, 故采用死循环接收
  3. - **发送端对象 -- 多个发送端的地址以及端口一直,可以形成简易聊天室**

public class SendDemo {
_public static void main
(String[] args) throws IOException {
// 创建发送端的Socket对象(DatagramSocket)
DatagramSocket ds = new DatagramSocket
();
// 需求要键盘录入 ,自己封装键盘录入数据
// 使用Scanner 键盘录入
// Scanner sc = new Scanner
(System._in);
// String line = sc.nextLine();** // 使用IO流中BufferedReader(字符缓冲输入流)实现 匿名内部类的InputStreamReader
BufferedReader br = new BufferedReader(_new InputStreamReader(System._in));
String line;
while ((_line = br.readLine())!=null){
if (line.equals(“886”)){
break; }
// 创建发送数据包,使用DatagramPacket打包数据
byte
[] bytes = line.getBytes();
// 使用DatagramPacket打包数据(字节数组, 字节数组长度, 主机名/IP, 端口号)
DatagramPacket dp = new DatagramPacket
(bytes, bytes.length, InetAddress._getByName(“127.0.0.1”),10086);
// 调用DatagramSocket对象的方法发送数据
ds.send(_dp); }
// 关闭发送端
ds.close
(); }}_

  1. - **接收端对象**

public class ReceiveDemo {
_public static void main
(String[] args) throws IOException {
// 创建接收端的Socket对象(DatagramSocket) // 创建接收端对象,并使用带参构造方法绑定数据DatagramSocket(int port)**
DatagramSocket ds = new DatagramSocket
(10086);
// 发送端键盘录入 ,只能接收一次,所以使用死循环
while
(true) {
// 创建接收数据包,用于接受发送端Socket对象的发来的数据
// 创建字节数组,定义字节数组长度用来接收数据
// 将定义接收的字节长度,以及字节对象传入到接收对象DatagramPacket中

byte
[] bytes = new byte[1024];
DatagramPacket dp = new DatagramPacket
(bytes, bytes.length)_;

  1. ** // 调用DatagramSocket对象的方法接收数据<br /> // 使用DatagramSocket的receive()方法**<br /> ds.receive_(_dp_)_;<br /> ** // 解析数据包,并把数据在控制台显示<br /> // 使用DatagramPacket中的getData()获取数据<br /> // 设置获取数据的长度,最后使用String转换字节并展示**<br /> System._out_.println_(_"数据是: " + new String_(_dp.getData_()_, 0, bytes.length_))_; _} }}_

TCP发送数据

TCP通信协议是一种可靠的网络协议,它在通信的两端各建立一个Socket对象,从而在通信的两端形成网络虚拟链路, 一旦建立了虚拟的网络链路,两端的程序就可以通过虚拟联络进行通信
Java对基于TCP协议的网络提供了良好的封装,使用Socket对象来代表两端的通信端口,并通过Socket产生IO流来进行网络通信
Java为客户端提供了Socket类,为服务器提供了ServerSocket类
image.png

TCP 发送数据

  1. 1. 创建客户端的Socket对象(Socket)
  2. 1. 获取输出流,写数据
  3. 1. 释放资源

Socket — 该类实现客户端套接字 (套接字是两台机器之间通讯的端点)

  1. - 创建客户端的Socket对象(Socket)
  2. - **Socket(String host, int port) 创建流套接字并将其连接到指定主机上的指定端口号**
  3. - ** Socket(InetAddress address, int port) 创建流套接字并将其连接到指定IP地址的指定端口号**
  4. - ** 两种构造函数,执行结果一致只是host的底层是InetAddress.getName()**
  5. - 获取输出流,写数据
  6. - ** OutputStream getOutputStream() 返回此套接字的输出流。 **
  7. - ** void write() 字节流资源 **
  8. - 释放资源
  9. - void close() 关闭资源

// 创建一个客户端类
public class ClientDemo {
_public static void main
(String[] args) throws IOException {
// 创建客户端的Socket对象(Socket)
// Socket(InetAddress address, int port) 创建流套接字并将其连接到指定IP地址的指定端口号
// Socket socket = new Socket(InetAddress.getByName(“127.0.0.1”),10086);
// Socket(String host, int port) 创建流套接字并将其连接到指定主机上的指定端口号
Socket socket = new Socket
(“127.0.0.1”,10086);
// 获取输出流,写数据, 使用字节输出流OutputStream类的getOutputStream()
// OutputStream getOutputStream() 返回此套接字的输出流
OutputStream os = socket.getOutputStream
();
// 使用OutputStream 字节流写入数据方法写数据
os.write
(“hello,world”.getBytes());
// 释放资源
socket.close
(); } }

TCP 接收数据

  1. 1. 创建服务端的Socket对象(ServerSocket)
  2. 1. 监听客户端Socket对象,并接收返回一个Socket对象
  3. 1. 获取输入流,读数据,并把数据显示在控制台
  4. 1. 释放资源

ServerSocket
—这个类实现了服务器套接字。 服务器套接字等待通过网络进入的请求。 它根据该请求执行一些操作,然后可能将结果返回给请求者

  1. - **创建客户端的Socket对象(ServerSocket)**
  2. - **ServerSocket(int port) 创建绑定到指定端口的服务器套接字**
  3. - **监听客户端Socket对象,并接收Socket对象**
  4. - **Socket accept() 侦听要连接到此套接字并接受它**
  5. - **因为服务端ServerSocket没有输入流方法,通过监听Socket对象获取**
  6. - **InputStream getInputStream() 返回此套接字的输入流**
  7. - **获取输入流,读数据,并把数据显示在控制台**
  8. - **字节读数据有两种方式,一次读一个字节流或者一次读一个字节流数组**
  9. - **释放资源**
  10. - **void close() 关闭资源**

// 创建一个服务端类
public class ServerDemo {
_public static void main
(String[] args) throws IOException {
// 创建服务端的Socket对象(ServerSocket)
// ServerSocket(int port) 创建绑定到指定端口的服务器套接字
ServerSocket serverSocket = new ServerSocket
(10086);
// Socket accept() 侦听要连接到此套接字并接受它
Socket socket = serverSocket.accept
();
// 因为服务端ServerSocket没有输入流方法,通过监听Socket对象获取
// InputStream getInputStream() 返回此套接字的输入流。
// 获取输入流,读数据,并把数据显示在控制台
InputStream inputStream = socket.getInputStream
();
// 字节读数据有两种方式,一次读一个字节流或者一次读一个字节流数组
byte
[] bytes = new byte[1024];
int len = inputStream.read
(bytes);
String data = new String
(bytes, 0, len);
System._out
.println(“数据是: “ + data);
// 释放资源
socket.close();
serverSocket.close(); }}

TCP 通信程序练习案例1

案例1:

  1. 1. 客户端:发送数据,接收服务器反馈
  2. 1. 客户端先写入数据,先写入getOutputStream() -- void write()
  3. 1. 再读取服务端反馈数据,读取getInputStream-- void read()
  4. 2. 服务端:接收数据,给出反馈
  5. 1. 服务端先读取数据,先读取getInputStream-- void read()
  6. 1. 再反馈给客户端数据,写入getOutputStream-- void write()

// 创建客户端Socket
public class ClientDemo {
_public static void main
(String[] args) throws IOException {
// 创建客户端Socket对象
Socket socket = new Socket
(“127.0.0.1”, 1995);
// 获取输出流对象使用getOutputStream()方法
OutputStream os = socket.getOutputStream
();
// 写数据 使用OutputStream的write()方法
os.write
(“hello,TCP服务端”.getBytes());
// 接收服务器的反馈使用getInputStream()方法
InputStream inputStream = socket.getInputStream
();
byte
[] bytes = new byte[1024];
int len = inputStream.read
(bytes);
String data = new String
(bytes, 0, len);
System._out
.println(“客户端: “ + data);
// 释放资源
socket.close(); }}
———————————————————
// 创建服务端ServerSocket
public class ServerDemo {
_public static void main
(String[] args) throws IOException {
// 创建服务端ServerSocket对象
ServerSocket serverSocket = new ServerSocket
(1995);
// 监听Socket对象,服务端同意accept()返回一个监听的Socket对象
Socket socket = serverSocket.accept
();
// 使用Socket中的InputStream的getInputStream()读取字节流
InputStream inputStream = socket.getInputStream
();
// 创建读取字节流数组
byte
[] bytes = new byte[1024];
int len = inputStream.read
(bytes);
String data = new String
(bytes, 0, len);
System._out
.println(“服务器: “ + data);
// 给出反馈使用OutputStream的getOutputStream
OutputStream outputStream = socket.getOutputStream();
outputStream.write(“TCP客户端你好!”.getBytes());
// 释放资源
serverSocket.close(); }}

TCP 通信程序练习案例2

案例2:

  1. 1. 客户端: 数据来源于键盘录入, 只到键盘输入的数据是886, 发送数据结束
  2. 1. 服务器: 接收到的数据在控制台输出
  3. 1. 使用字符串传递
  4. - 客户端使用BfferedWriter,获取字节转为字符
  5. - BufferedReader bf = new BufferedReader**(**new InputStreamReader**(**System.in**))**;
  6. - BufferedWriter bw = new BufferedWriter**(**new OutputStreamWriter**(**socket.getOutputStream**()))**;
  7. - 服务端使用BufferedReader
  8. - BufferedReader bfr= new BufferedReader**(**new InputStreamReader**(**socket.getInputStream**()))**;
  9. - 代码实现:_// 创建客户端对象.实现传送字符流<br />public class ClientDemo **{<br /> **public static void main**(**String**[] **_args_**) **throws IOException **{<br /> **// 创建客户端对象<br /> Socket socket = new Socket**(**"127.0.0.1", 110**)**;
  10. // 使用BufferedRead缓冲字符流实现,使用匿名内部类InputStreamReader写数据<br /> BufferedReader bf = new BufferedReader**(**new InputStreamReader**(**System.in**))**;
  11. // 尝试一次写一个字符串,不写入字节流,封装输出流对象,写入字符流<br /> // 和缓冲写入字符串BufferedRead一致,使用缓冲字符流读取<br /> /*代码解析:<br /> 1.创建BufferedWriter对象,<br /> 2.匿名内部类获取字符流OutputStreamWriter<br /> 3.转换获取的getOutputStream字节流*/<br /> BufferedWriter bw = new BufferedWriter**(**new OutputStreamWriter**(**socket.getOutputStream**()))**;<br /> // 数据来源于键盘录入,直到输入的数据886,<br /> String line;<br /> while **((**line = bf.readLine**()) **!= null**) {<br /> **if **(**line.equals**(**"886"**)) { **break; **}<br /> **// 使用字符串写入三步骤,write(),newLine(),flush()<br /> bw.write**(**line**)**;<br /> bw.newLine**()**;<br /> bw.flush**()**;<br /> // 获取客户端输出流对象,使用Socket类中的getOutputStream<br /> // OutputStream outputStream = socket.getOutputStream();<br /> // 获取的line一行字符,转换为字节数组写入<br /> // outputStream.write(line.getBytes()) **}<br /> **// 释放资源<br /> socket.close**()**; **}}<br />-------------------------------------------------------**

public class ServerDemo {
public static void main(String[] args) throws IOException {
// 创建服务器ServerSocket对象,绑定客户端的端口号
ServerSocket serverSocket = new ServerSocket(110);
// 监听客户端的连接,并返回接受accept的Socket对象
Socket socket = serverSocket.accept();
/ 获取输入流
InputStream inputStream = socket.getInputStream();
// 客户端发送的是OutputStreamWriter字符输出流.所以使用InputStreamReader字符输入流获取
InputStreamReader isr = new InputStreamReader(inputStream);
BufferedReader bfr = new BufferedReader(isr);
/
BufferedReader bfr= new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line;
while ((line = bfr.readLine())!=null){ System.out.println(line); }
// 释放资源
serverSocket.close(); **} }

**

TCP 通信程序练习案例3

  1. - 客户端: 数据来源于键盘录入,直到输入的数据是886, 发送数据结束
  2. - 服务器: 接收到的数据写入文本文件

代码实现:
public class FileServerDemo {
public static void main(String[] args) throws IOException {
// 创建服务器ServerSocket对象
ServerSocket serverSocket = new ServerSocket(100);
// 服务端监听客户端连接,并接收客户端返回的Socket对象
Socket socket = serverSocket.accept();
// 使用Socket对象获取数据
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
// 将数据写入文本文件,使用BufferedWriter的FileWriter
BufferedWriter bw = new BufferedWriter(new FileWriter(“D:\Program Files\test01\test.txt”));
// 定义数据类型,获取数据
String line;
while ((line= br.readLine())!=null){
// 使用文本BufferedWriter三件套写入文本文件
bw.write(line);
bw.newLine();
bw.flush();
System.out.println(line); }
// 释放服务端,但是文件写入的bw并没有释放,所以要释放资源
bw.close();
serverSocket.close(); }}
————————————————————————————-
public class ClientDemo {
public static void main(String[] args) throws IOException {
//创建客户端对象
Socket socket = new Socket(“127.0.0.1”,100);
// 客服端获取字节输出流 使用BufferedReader获取键盘录入数据
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
// 使用BufferedWriter封装输出流
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
// 调用封装的方法
buffered(socket, br, bw); }
// 封装输出流对象为方法,将socket客户端对象,字节输出流br ,以及字节输入流传入
public static void buffered(Socket socket, BufferedReader br, BufferedWriter bw) throws IOException {
String line;
while ((line= br.readLine())!=null){
if (line.equals(“886”)){ break; }
// 缓冲流写入写入三件套
bw.write(line);
bw.newLine();
bw.flush(); }
socket.close(); **} }

TCP 通信程序练习案例4

  1. - 客户端: 数据来自于文本文件
  2. - 服务端: 接收到的数据写入文本文件

代码实现:
public class FileServerDemo {
public static void main(String[] args) throws IOException {
// 创建服务器端对象
ServerSocket serverSocket = new ServerSocket(111);
// 服务器端对象接收一个Socket对象
Socket socket = serverSocket.accept();
// 使用Socket服务器端对象获取数据
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
// 获取的数据写入文本文件中
BufferedWriter bw = new BufferedWriter(new FileWriter(“D:\Program Files\test01\test01.txt”));
// 写入字符流
String line;
while ((line = br.readLine())!=null){
bw.write(line);
bw.newLine();
bw.flush(); }
// 释放资源
bw.close();
serverSocket.close(); } }
——————————————————————-
public class FileClientDemo {
public static void main(String[] args) throws IOException {
// 创建客户端对象
Socket socket = new Socket(“127.0.0.1”,111);
// 添加客户端文本写入流使用BufferedRead的FileReader
BufferedReader br = new BufferedReader(new FileReader(“D:\Program Files\test01\test.txt”));
// 封装从Buffered写入的文本数据流
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
// 写数据三件套
String line;
while ((line= br.readLine())!=null){
bw.write(line);
bw.newLine();
bw.close(); }
// 释放资源
br.close();
socket.close(); }}

TCP 通信程序练习案例5

  1. - 客户端: 数据来自于文本文件,接收服务器反馈
  2. - 服务端: 接收到的数据写入文本文件,给出反馈
  3. - 反馈出现问题:程序一直等待 没有反馈
  4. - 原因: 读数据的方法是阻塞式的 一步一步往下走
  5. - 解救方法: 使用Socket类中的shutdownOutput() 方法

public class FileClientDemo {
public static void main(String[] args) throws IOException {
// 创建客户端对象
Socket socket = new Socket(“127.0.0.1”, 1111);
// 添加客户端文本写入流使用BufferedRead的FileReader
BufferedReader br = new BufferedReader(new FileReader(“D:\Program Files\test01\src\com05\ClientDemo.java”));
// 封装从Buffered写入的文本数据流
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
// 写数据三件套
String line;
while ((line = br.readLine()) != null) {
bw.write(line);
bw.newLine();
bw.flush(); }
// 自定义写入数据结束标记,但是如果文件中有相同字符串则直接结束
/ bw.write(“goodbye”);
bw.newLine();
bw.flush();
/
// 使用Socket类中的停止写入标记方法
// public void shutdownOutput() 结束标记
socket.shutdownOutput();
// 客户端给出反馈,使用BufferedReader接收数据
BufferedReader SocketBr = new BufferedReader(new InputStreamReader(socket.getInputStream()));
// 只读取一次
String data = SocketBr.readLine();
System.out.println(“服务器的反馈: “ + data);
// 释放资源
br.close();
socket.close(); } }
—————————————————————————————————————————-
public class FileServerDemo {
public static void main(String[] _args
) throws IOException {
// 创建服务器端对象
ServerSocket serverSocket = new ServerSocket(1111);
// 服务器端对象接收一个Socket对象
Socket socket = serverSocket.accept();
// 使用Socket服务器端对象获取数据
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
// 获取的数据写入文本文件中
BufferedWriter bw = new BufferedWriter(new FileWriter(“D:\Program Files\test01\test.txt”));
// 写入字符流
String line;
while ((line = br.readLine())!=null){
// 判断客户端写入结束标记
/ if (line.equals(“goodbye”)){
break;
}
/
bw.write(line);
bw.newLine();
bw.flush(); }
// 给出反馈,使用BufferedReader封装
BufferedWriter ServerBw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
ServerBw.write(“文件上传成功”);
ServerBw.newLine();
ServerBw.flush();
// 释放资源
bw.close();
serverSocket.close(); } }

TCP 通信程序练习案例6

  1. - 客户端: 数据来自于文本文件,接收服务器反馈
  2. - 服务端: 接收到的数据写入文本文件,给出反馈,并且代码用线程进行封装,为每一个客户端开启一个线程

// 客户端对象
public class FileClientDemo {
public static void main(String[] args) throws IOException {
// 创建客户端对象
Socket socket = new Socket(“127.0.0.1”, 11111);
// 添加客户端文本写入流使用BufferedRead的FileReader
BufferedReader br = new BufferedReader(new FileReader(“D:\Program Files\test01\src\com05\ClientDemo.java”));
// 封装从Buffered写入的文本数据流
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
// 写数据三件套
String line;
while ((line = br.readLine()) != null) {
bw.write(line);
bw.newLine();
bw.flush(); }
// 自定义写入数据结束标记
// public void shutdownOutput() 结束标记
socket.shutdownOutput();
// 客户端给出反馈,使用BufferedReader接收数据
BufferedReader SocketBr = new BufferedReader(new InputStreamReader(socket.getInputStream()));
// 只读取一次
String data = SocketBr.readLine();
System.out.println(“服务器的反馈: “ + data);
// 释放资源
br.close();
socket.close(); } }
——————————————————————
// 服务器对象
// 创建一个服务器对象,并且创建Socket的线程类,实现Runnable多线程
public class FileServerDemo {
public static void main(String[] _args
) throws IOException {
// 创建服务器端对象
ServerSocket serverSocket = new ServerSocket(11111);
// 始终开启服务端
while (true) {
// 服务器端对象接收一个Socket对象
Socket socket = serverSocket.accept();
// 为每一个客户端开启一个线程,创建一个类,实现Runnable接口完成多线程
new Thread(new ServerThread(socket)).start(); } }}
===========================================
// 实现多线程Runnable的对象
// 创建一个Socket类实现Runnable接口
public class ServerThread implements Runnable {
private Socket socket;
public ServerThread(Socket socket) { this.socket = socket; }
@Override
_public void run() {
// 接收文本数据写入文本文件
// 接收文本数据也就是读取文本数据 new InputStreamReader(socket.getInputStream())
try {
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
// 解决名称冲突问题,每个客户端传给服务端都是一个文件名
// 定义随机文件名
int count = 0; // 现在文件名为test0.txt
File file = new File(“D:\Program Files\test01\test[“ + count + “].txt”);
// 循环判断文件是否存在,如果存在生成test++.txt
while (file.exists()){
count++;
file = new File(“D:\Program Files\test01\test[“ + count + “].txt”); }
BufferedWriter bw = new BufferedWriter(new FileWriter(file));
String line;
while ((line = br.readLine()) != null) {
bw.write(line);
bw.newLine();
bw.flush(); }
// 服务器给出反馈 —写入数据给客户端
// 写入文本数据 new OutputStreamWriter(socket.getOutputStream())
BufferedWriter ServerBw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
ServerBw.write(“文件上传成功!”);
} catch (IOException _e
) {
e.printStackTrace(); } } }
**