二、网络编程
- 网络编程入门
- UDP通信程序
- TCP通信程序
计算机网络
网络编程概述
在网络通信协议下,实现网络互连的不同计算机上运行的程序间可以进行数据交换。
网络编程三要素
IP地址
InetAddress的使用
案例:
/**
* @Author TeaBowl
* @Date 2021/3/26 16:46
* @Version 1.0
*/
public class InetAddressDemo1 {
public static void main(String[] args) throws Exception {
//确定主机的IP地址
//主机名称可以是机器名称或者IP地址
//InetAddress address = InetAddress.getByName("wz");
InetAddress address = InetAddress.getByName("192.168.142.1");
//获取此IP地址的主机名
String hostName = address.getHostName();
//获得IP地址
String hostAddress = address.getHostAddress();
System.out.println("主机名:" + hostName);
System.out.println("IP地址:" + hostAddress);
}
}
控制台:
主机名:wz
IP地址:192.168.142.1
端口
协议
三次握手:
UDP通信原理
UDP发送数据
/**
* @Author TeaBowl
* @Date 2021/3/26 17:10
* @Version 1.0
*/
public class UdpSendDemo {
public static void main(String[] args) throws Exception {
//创建发送端Socket对象(DatagramSocket)
DatagramSocket socket = new DatagramSocket();
//创建数据,打包数据
//DatagramPacket(byte buf[], int length,InetAddress address, int port)
String s = "hello UDP 我来了";
/*byte[] bys = s.getBytes();
int len = bys.length;
InetAddress address = InetAddress.getByName("wz");
int port = 10099;
DatagramPacket packet = new DatagramPacket(bys,len,address,port);*/
DatagramPacket packet = new DatagramPacket(
s.getBytes(),
s.getBytes().length,
InetAddress.getByName("wz"),
10099);
//调用DatagramSocket对象的send()方法发送数据
socket.send(packet);
//关闭发送端
socket.close();
}
}
UDP接收数据
/**
* @Author TeaBowl
* @Date 2021/3/26 17:29
* @Version 1.0
*/
public class ReceiveDemo {
public static void main(String[] args) throws Exception {
//创建Socket对象
DatagramSocket socket = new DatagramSocket(10099);
//创建数据包bytes,用于接收数据
byte[] bytes = new byte[1024];
DatagramPacket packet = new DatagramPacket(bytes, bytes.length);
//接收数据
socket.receive(packet);
//解析数据包,把数据包里的数据data显示在控制台
byte[] data = packet.getData();
//int getLength():返回要发送的数据的长度或者接收到的数据的长度
int length = packet.getLength();
//接收到的字符串
String s = new String(data,0,length);
System.out.println("数据是:" + s);
//关闭接收端
socket.close();
}
}
先开启接收端,再运行发送端
接收端控制台:
数据是:hello UDP 我来了
UDP通信程序练习
按照下面的要求实现程序:
- UDP发送数据:数据来自于键盘录入,直到输入的数据是886,发送数据结束。
- UDP接收数据:因为接收端不知道发送端什么时候停止发送,故采用死循环接收。
/**
* @Author TeaBowl
* @Date 2021/4/3 3:22
* @Version 1.0
* - UDP发送数据:数据来自于键盘录入,直到输入的数据是886,发送数据结束。
*/
public class SendDemo {
public static void main(String[] args) throws Exception {
//创建发送端的Socket对象(DatagramSocket)
DatagramSocket socket = new DatagramSocket();
//自己封装键盘录入数据
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String line;
//如果输入的数据不为空
while ((line= br.readLine())!=null){
//如果输入的数据是886,发送数据结束
if("886".equals(line)){
break;
}
//创建数据,并把数据打包
//输入的数据转为字节数组
byte[] bytes = line.getBytes();
//数据打包
DatagramPacket packet = new DatagramPacket(bytes, bytes.length, InetAddress.getByName("wz"), 12345);
//调用DatagramSocket对象的方法发送数据
socket.send(packet);
}
//关闭发送端
socket.close();
}
}
/**
* @Author TeaBowl
* @Date 2021/4/3 3:22
* @Version 1.0
* - UDP接收数据:因为接收端不知道发送端什么时候停止发送,故采用死循环接收。
*/
public class ReceiveDemo {
public static void main(String[] args) throws Exception {
//创建发送端的Socket对象(DatagramSocket) 参数:端口号
DatagramSocket socket = new DatagramSocket(12345);
//死循环接收数据
while (true){
//创建一个数据包,用于接收数据
byte[] bytes = new byte[1024];
DatagramPacket packet = new DatagramPacket(bytes, bytes.length);
//调用DatagramSocket对象的方法接收数据
socket.receive(packet);
//解析数据包,并把数据在控制台显示
//参数:接收到的数据包,0,数据长度
System.out.println("数据是:"+new String(packet.getData(),0, packet.getLength()));
}
//关闭接收端
//socket.close();
}
}
控制台显示:
SendDemo:
hello
world
java
886
Process finished with exit code 0 出现886,发送结束了
ReceiveDemo:
数据是:hello
数据是:world
数据是:java
没结束,一直接收数据
聊天室演示(开启多个发送端):
SendDemo1:
我是1号,我爱柳岩
3号老哥牛批
886
Process finished with exit code 0 出现886,发送结束了
SendDemo2:
我是2号,我爱刘亦菲
兄弟666
886
Process finished with exit code 0 出现886,发送结束了
SendDemo3:
我是3号,我爱刘老根
哇哈哈
886
Process finished with exit code 0 出现886,发送结束了
ReceiveDemo:
数据是:我是1号,我爱柳岩
数据是:我是2号,我爱刘亦菲
数据是:我是3号,我爱刘老根
数据是:3号老哥牛批
数据是:兄弟666
数据是:哇哈哈
没结束,一直接收数据
TCP通信原理
TCP通信协议是一种可靠的网络协议,它在通信的两端各建立了一个Socket对象,从而在通信的两端形成网络虚拟链路,一旦建立了虚拟的网络链路,两端的程序就可以通过虚拟链路进行通信。
Java对基于TCP协议的网络提供了良好的封装,使用Socket对象来代表两端的通信端口,并通过Socket产生IO流来进行网络通信。
Java为客户端提供了Socket类,为服务器提供了ServerSocket类。
TCP发送数据
/**
* @Author TeaBowl
* @Date 2021/4/3 4:41
* @Version 1.0
* TCP发送数据的步骤
* 创建客户端的Socket对象
* 获取输出流,写数据
* 释放资源
*/
public class ClientDemo {
public static void main(String[] args) throws Exception {
//创建客户端的Socket对象
//Socket(InetAddress address,int port):创建流套接字并将其链接到指定IP地址的指定端口号
//Socket socket = new Socket(InetAddress.getByName("wz"), 10000);
//Socket(String host,int port):创建流套接字并将其链接到指定IP地址的指定端口号
Socket socket = new Socket("wz", 10000);
//获取输出流,写数据
//OutputStream getOutputStream():返回此套接字的输出流
OutputStream outputStream = socket.getOutputStream();
outputStream.write("hello,tcp,我来了".getBytes());
//释放资源
socket.close();
}
}
TCP接收数据
/**
* @Author TeaBowl
* @Date 2021/4/3 4:57
* @Version 1.0
* TCP接受数据的步骤:
* 创建服务器端的Socket对象(ServerSocket)
* 获取输入流,读数据,并把数据显示在控制台
* 释放资源
*/
public class ServerDemo {
public static void main(String[] args) throws Exception {
//创建服务器端的Socket对象
//ServerSocket(int port):创建绑定到指定端口的服务器套接字
ServerSocket serverSocket = new ServerSocket(10000);
//Socket accept():侦听要连接到此的套接字,并接受它
//即:监听客户端有连接时,对应地生成一个Socket对象
Socket accept = serverSocket.accept();
//获取输入流,读数据,并把数据显示在控制台
InputStream inputStream = accept.getInputStream();
//读数据,字节数组
//创建一个数据包,用于接收数据
byte[] bytes = new byte[1024];
//读取数据包长度
int len = inputStream.read(bytes);
//将读到的数据流,字节流转字符串
//参数(数据包,0,长度)
String data = new String(bytes, 0, len);
System.out.println("数据是:" + data);
//释放资源
accept.close();
serverSocket.close();
}
}
控制台:
ServerDemo:
数据是:hello,tcp,我来了
Process finished with exit code 0
TCP通信程序练习
练习1:
- 客户端:发送数据,接收服务器反馈
- 服务器:接收数据,给出反馈
/**
* @Author TeaBowl
* @Date 2021/4/3 4:41
* @Version 1.0
* 客户端:发送数据,接收服务器反馈
*/
public class ClientDemo {
public static void main(String[] args) throws Exception {
//创建客户端的Socket对象
Socket socket = new Socket("wz", 10001);
//获取输出流,写数据
OutputStream outputStream = socket.getOutputStream();
outputStream.write("你好啊,茉莉花茶".getBytes());
//接收服务器反馈
//创建输入流
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);
//释放资源
//inputStream.close();
//outputStream.close();
socket.close();
}
}
/**
* @Author TeaBowl
* @Date 2021/4/3 4:57
* @Version 1.0
* 服务器:接收数据,给出反馈
*/
public class ServerDemo {
public static void main(String[] args) throws Exception {
//创建服务器端的Socket对象(ServerSocket)
ServerSocket serverSocket = new ServerSocket(10001);
//监听客户端连接,返回一个Socket对象
Socket accept = serverSocket.accept();
//获取输入流,读数据,并把数据显示在控制台
InputStream inputStream = accept.getInputStream();
byte[] bytes = new byte[1024];
int len = inputStream.read(bytes);
String data = new String(bytes, 0, len);
System.out.println("服务器:" + data);
//给客户端反馈
OutputStream outputStream = accept.getOutputStream();
outputStream.write("数据已经收到".getBytes());
//释放资源
//accept.close();
serverSocket.close();
}
}
控制台:
ServerDemo:
服务器:你好啊,茉莉花茶
Process finished with exit code 0
ClientDemo:
客户端:数据已经收到
Process finished with exit code 0
练习2:
- 客户端:数据来自于键盘录入,直到输入的数据是886,发送数据结束
- 服务器:接收到的数据在控制台输出
/**
* @Author TeaBowl
* @Date 2021/4/3 4:41
* @Version 1.0
* 客户端:数据来自于键盘录入,直到输入的数据是886,发送数据结束
*/
public class ClientDemo {
public static void main(String[] args) throws Exception {
//创建客户端的Socket对象
Socket socket = new Socket("wz", 10002);
//键盘录入数据,直到输入886,发送数据结束
//键盘录入的数据
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
/**
* 封装输出流对象
* socket.getOutputStream() 获取字节输出流对象
* new OutputStreamWriter(输出流对象) 输出流转为字符流对象
* new BufferedWriter() 创建写入数据的对象
*/
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
String line;
while ((line = bufferedReader.readLine()) != null) {
if ("886".equals(line)) {
break;
}
//发送数据
//写数据 键盘录入的数据
bufferedWriter.write(line);
//换行
bufferedWriter.newLine();
//刷新
bufferedWriter.flush();
}
//释放资源
socket.close();
}
}
/**
* @Author TeaBowl
* @Date 2021/4/3 4:57
* @Version 1.0
* 服务器:接收到的数据在控制台输出
*/
public class ServerDemo {
public static void main(String[] args) throws Exception {
//创建服务器端的Socket对象(ServerSocket)
ServerSocket serverSocket = new ServerSocket(10002);
//监听客户端连接
Socket accept = serverSocket.accept();
//获取输入流
//字节流转为字符流,再包装为BufferedReader对象
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(accept.getInputStream()));
String line;
//如果读取的数据不为空,输出数据为字符串
while ((line = bufferedReader.readLine()) != null) {
//接收到的数据在控制台输出
System.out.println(line);
}
//释放资源
serverSocket.close();
}
}
控制台:
ClientDemo:
hello
world
java
886
Process finished with exit code 0
ServerDemo:
hello
world
java
Process finished with exit code 0
练习3:
- 客户端:数据来自于键盘录入,直到输入的数据是886,发送数据结束
- 服务器:接收到的数据写入文本文件
/**
* @Author TeaBowl
* @Date 2021/4/3 4:41
* @Version 1.0
* 客户端:数据来自于键盘录入,直到输入的数据是886,发送数据结束
*/
public class ClientDemo {
public static void main(String[] args) throws Exception {
//创建客户端的Socket对象
Socket socket = new Socket("wz", 10003);
//键盘录入数据,直到输入886,发送数据结束
//键盘录入的数据
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
/**
* 封装输出流对象
* socket.getOutputStream() 获取字节输出流对象
* new OutputStreamWriter(输出流对象) 输出流转为字符流对象
* new BufferedWriter() 创建写入数据的对象
*/
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
String line;
while ((line = bufferedReader.readLine()) != null) {
if ("886".equals(line)) {
break;
}
//发送数据
//写数据 键盘录入的数据
bufferedWriter.write(line);
//换行
bufferedWriter.newLine();
//刷新
bufferedWriter.flush();
}
//释放资源
socket.close();
}
}
/**
* @Author TeaBowl
* @Date 2021/4/3 4:57
* @Version 1.0
* 服务器:接收到的数据写入文本文件
*/
public class ServerDemo {
public static void main(String[] args) throws Exception {
//创建服务器端的Socket对象(ServerSocket)
ServerSocket serverSocket = new ServerSocket(10003);
//监听客户端连接,返回一个socket对象
Socket accept = serverSocket.accept();
//获取输入流
//字节流转为字符流,再包装为BufferedReader对象
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(accept.getInputStream()));
//将字符流写入"my\\file.txt"的操作,包装成BufferedWriter对象
BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter("my\\file.txt"));
String line;
//如果读到的数据不为空
while ((line = bufferedReader.readLine()) != null) {
bufferedWriter.write(line);
bufferedWriter.newLine();
bufferedWriter.flush();
}
//释放资源
bufferedWriter.close();
serverSocket.close();
}
}
控制台:
ClientDemo:
hello
java
886
Process finished with exit code 0
ServerDemo:
Process finished with exit code 0
练习4:
- 客户端:数据来自于文本文件
- 服务器:接收到的数据写入文本文件
/**
* @Author TeaBowl
* @Date 2021/4/3 4:41
* @Version 1.0
* 客户端:数据来自于文本文件
*/
public class ClientDemo {
public static void main(String[] args) throws Exception {
//创建客户端Socket对象
Socket socket = new Socket("wz", 10003);
//读取文件 封装文本文件的数据,
BufferedReader bufferedReader = new BufferedReader(new FileReader("myThreadTest\\静夜思.txt"));
//发送数据 封装输出流写数据
//OutputStreamWriter 字符流转为字节流
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
//读数据,写出去
String line;
//readLine() 读取一行数据
while ((line = bufferedReader.readLine()) != null) {
//写数据
bufferedWriter.write(line);
//换行
bufferedWriter.newLine();
//强制输出缓冲区数据
bufferedWriter.flush();
}
//释放资源
//停止读数据操作
bufferedReader.close();
//关闭客户端Socket对象
socket.close();
}
}
/**
* @Author TeaBowl
* @Date 2021/4/3 4:57
* @Version 1.0
* 服务器:接收到的数据写入文本文件
*/
public class ServerDemo {
public static void main(String[] args) throws Exception {
//创建服务器端的Socket对象(ServerSocket)
ServerSocket serverSocket = new ServerSocket(10003);
//监听客户端连接,返回一个socket对象
Socket accept = serverSocket.accept();
//获取输入流
//字节流转为字符流,再包装为BufferedReader对象
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(accept.getInputStream()));
//将字符流写入"my\\chawaner.txt"的操作,包装成BufferedWriter对象
BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter("myThreadTest\\chawaner.txt"));
String line;
//如果读到的数据不为空
while ((line = bufferedReader.readLine()) != null) {
bufferedWriter.write(line);
bufferedWriter.newLine();
bufferedWriter.flush();
}
//释放资源
bufferedWriter.close();
serverSocket.close();
}
}
控制台:
ServerDemo:
Process finished with exit code 0
ClientDemo:
Process finished with exit code 0
练习5:
- 客户端:数据来自于文本文件,接收服务器反馈
- 服务器:接收到的数据写入文本文件,给出反馈
- 出现问题:程序一直等待
- 原因:读数据的方式是阻塞式的
- 解决办法:自定义结束标记;推荐使用shutdownOutput()方法。
不使用结束标记时,一直在等待读取数据,程序不能执行成功。
所以得使用结束标记,下面使用了”自定义结束标记“。
/**
* @Author TeaBowl
* @Date 2021/4/3 4:41
* @Version 1.0
* 客户端:数据来自于文本文件,接收服务器反馈
*/
public class ClientDemo {
public static void main(String[] args) throws Exception {
//创建客户端Socket对象
Socket socket = new Socket("wz", 10003);
//读取文件 封装文本文件的数据,
BufferedReader bufferedReader = new BufferedReader(new FileReader("myThreadTest\\静夜思.txt"));
//发送数据 封装输出流写数据
//OutputStreamWriter 字符流转为字节流
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
//读数据,写出去
String line;
//readLine() 读取一行数据
while ((line = bufferedReader.readLine()) != null) {
//写数据
bufferedWriter.write(line);
//换行
bufferedWriter.newLine();
//强制输出缓冲区数据
bufferedWriter.flush();
}
//自定义结束标记
bufferedWriter.write("886");
bufferedWriter.newLine();
bufferedWriter.flush();
//接收反馈
BufferedReader bufferedReader1 = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String data = bufferedReader1.readLine();
System.out.println("服务器的反馈:" + data);
//释放资源
//停止读数据操作
bufferedReader.close();
//关闭客户端Socket对象
socket.close();
}
}
/**
* @Author TeaBowl
* @Date 2021/4/3 4:57
* @Version 1.0
* 服务器:接收到的数据写入文本文件,给出反馈
*/
public class ServerDemo {
public static void main(String[] args) throws Exception {
//创建服务器端的Socket对象(ServerSocket)
ServerSocket serverSocket = new ServerSocket(10003);
//监听客户端连接,返回一个对应的Socket对象
Socket accept = serverSocket.accept();
//接收数据
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(accept.getInputStream()));
//把数据写入文本文件
BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter("myThreadTest\\hello.txt"));
String line;
while ((line = bufferedReader.readLine()) != null) {//等待读取数据
//判断结束标记
if ("886".equals(line)){
break;
}
bufferedWriter.write(line);
bufferedWriter.newLine();
bufferedWriter.flush();
}
//给出反馈
BufferedWriter bufferedWriter1 = new BufferedWriter(new OutputStreamWriter(accept.getOutputStream()));
bufferedWriter1.write("文件上传成功!");
bufferedWriter1.newLine();
bufferedWriter1.flush();
//释放资源
bufferedWriter.close();
serverSocket.close();
}
}
控制台:
ClientDemo:
服务器的反馈:文件上传成功!
Process finished with exit code 0
ServerDemo:
Process finished with exit code 0
注意:
自定义结束标签的缺点是:如果接收到的文件里有“886”这个字段,那么就会结束文件的写入;写入的文件不包括“886”关键字之后的内容。
使用shutdownOutput和shutdownInput()结束标记方法对客户端和服务器端进行修改:
/**
* @Author TeaBowl
* @Date 2021/4/3 4:41
* @Version 1.0
* 客户端:数据来自于文本文件,接收服务器反馈
*/
public class ClientDemo {
public static void main(String[] args) throws Exception {
//创建客户端Socket对象
Socket socket = new Socket("wz", 10003);
//读取文件 封装文本文件的数据,
BufferedReader bufferedReader = new BufferedReader(new FileReader("myThreadTest\\静夜思.txt"));
//发送数据 封装输出流写数据
//OutputStreamWriter 字符流转为字节流
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
//读数据,写出去
String line;
//readLine() 读取一行数据
while ((line = bufferedReader.readLine()) != null) {
//写数据
bufferedWriter.write(line);
//换行
bufferedWriter.newLine();
//强制输出缓冲区数据
bufferedWriter.flush();
}
//自定义结束标记
//bufferedWriter.write("886");
//bufferedWriter.newLine();
//bufferedWriter.flush();
//结束标记方法 表示输出结束
socket.shutdownOutput();
//接收反馈
BufferedReader bufferedReader1 = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//等待读取数据
String data = bufferedReader1.readLine();
System.out.println("服务器的反馈:" + data);
//释放资源
//停止读数据操作
bufferedReader.close();
//关闭客户端Socket对象
socket.close();
}
}
/**
* @Author TeaBowl
* @Date 2021/4/3 4:57
* @Version 1.0
* 服务器:接收到的数据写入文本文件,给出反馈
*/
public class ServerDemo {
public static void main(String[] args) throws Exception {
//创建服务器端的Socket对象(ServerSocket)
ServerSocket serverSocket = new ServerSocket(10003);
//监听客户端连接,返回一个对应的Socket对象
Socket accept = serverSocket.accept();
//接收数据
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(accept.getInputStream()));
//把数据写入文本文件
BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter("myThreadTest\\hello.txt"));
String line;
while ((line = bufferedReader.readLine()) != null) {//等待读取数据
//判断结束标记
//if ("886".equals(line)){
// break;
//}
bufferedWriter.write(line);
bufferedWriter.newLine();
bufferedWriter.flush();
}
//给出反馈
BufferedWriter bufferedWriter1 = new BufferedWriter(new OutputStreamWriter(accept.getOutputStream()));
bufferedWriter1.write("文件上传成功!");
bufferedWriter1.newLine();
bufferedWriter1.flush();
//释放资源
bufferedWriter.close();
serverSocket.close();
}
}
控制台:
ClientDemo:
服务器的反馈:文件上传成功!
Process finished with exit code 0
ServerDemo:
Process finished with exit code 0
练习6:
- 客户端:数据来自于文本文件,接收服务器反馈
- 服务器:接收到的数据写入文本文件,给出反馈,代码用线程封装,为每一个客户端开启一个线程
/**
* @Author TeaBowl
* @Date 2021/4/3 4:41
* @Version 1.0
* 客户端:数据来自于文本文件,接收服务器反馈
*/
public class ClientDemo {
public static void main(String[] args) throws Exception {
//创建客户端Socket对象
Socket socket = new Socket("wz", 10003);
//读取文件 封装文本文件的数据,
BufferedReader bufferedReader = new BufferedReader(new FileReader("myThreadTest\\静夜思.txt"));
//发送数据 封装输出流写数据
//OutputStreamWriter 字符流转为字节流
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
//读数据,写出去
String line;
//readLine() 读取一行数据
while ((line = bufferedReader.readLine()) != null) {
//写数据
bufferedWriter.write(line);
//换行
bufferedWriter.newLine();
//强制输出缓冲区数据
bufferedWriter.flush();
}
//结束标记方法 表示输出结束
socket.shutdownOutput();
//接收反馈
BufferedReader bufferedReader1 = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//等待读取数据
String data = bufferedReader1.readLine();
System.out.println("服务器的反馈:" + data);
//释放资源
//停止读数据操作
bufferedReader.close();
//关闭客户端Socket对象
socket.close();
}
}
/**
* @Author TeaBowl
* @Date 2021/4/3 4:57
* @Version 1.0
* 服务器:接收到的数据写入文本文件,给出反馈,代码用线程封装,为每一个客户端开启一个线程
*/
public class ServerDemo {
public static void main(String[] args) throws Exception {
//创建服务器端的Socket对象(ServerSocket)
ServerSocket serverSocket = new ServerSocket(10003);
while (true){
//监听客户端连接,返回一个对应的Socket对象
Socket accept = serverSocket.accept();
//为每一个客户端开启一个线程
//ServerThread类实现Runnable接口,并重写run()方法
new Thread(new ServerThread(accept)).start();
}
//服务器不关闭
//serverSocket.close();
}
}
/**
* @Author TeaBowl
* @Date 2021/4/5 14:16
* @Version 1.0
* ServerThread类:实现Runnable接口,并重写run()方法
*/
public class ServerThread implements Runnable {
private Socket accept;
public ServerThread(Socket accept) {
this.accept = accept;
}
@Override
public void run() {
try {
//接收数据写入到文本文件
//接收数据
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(accept.getInputStream()));
//BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter("myThreadTest\\Copy.txt"));
//解决名称冲突问题
int count=0;
File file = new File("myThreadTest\\Copy["+count+"].txt");
//如果文件名存在
while (file.exists()){
count++;
file = new File("myThreadTest\\Copy["+count+"].txt");
}
//写入数据到文件
BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(file));
//读到的数据不为空时,写入数据
String line;
while ((line=bufferedReader.readLine())!=null){
bufferedWriter.write(line);
bufferedWriter.newLine();
bufferedWriter.flush();
}
//给出反馈
BufferedWriter bufferedWriter1 = new BufferedWriter(new OutputStreamWriter(accept.getOutputStream()));
bufferedWriter1.write("文件上传成功");
bufferedWriter1.newLine();
bufferedWriter1.flush();
//释放资源 关闭连接
accept.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
控制台:
ServerDemo:
ClientDemo:
服务器的反馈:文件上传成功
Process finished with exit code 0
ClientDemo1:
服务器的反馈:文件上传成功
Process finished with exit code 0
ClientDemo2:
服务器的反馈:文件上传成功
Process finished with exit code 0