练习1:多发多收
客户端:多次发送数据
服务器:多次接收数据,并打印
客户端:
package a09tcpdemo;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Scanner;
public class Client1 {
public static void main(String[] args) throws IOException {
//1.创建Socket对象并连接服务端
Socket socket=new Socket("127.0.0.1",10001);
//2.写出数据
Scanner sc=new Scanner(System.in);
OutputStream os = socket.getOutputStream();
while (true) {
System.out.println("请输入您要发送的信息");
String str = sc.nextLine();
if("886".equals(str)){
break;
}
os.write(str.getBytes());
}
//3.释放资源
socket.close();
}
}
服务器端:
package a09tcpdemo;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
public class Server1 {
public static void main(String[] args) throws IOException {
//1.创建对象绑定端口
ServerSocket ss=new ServerSocket(10001);
//2.等待客户端连接
Socket socket = ss.accept();
//3.读取数据
InputStreamReader isr=new InputStreamReader(socket.getInputStream());
int b;
while((b=isr.read())!=-1){
System.out.print((char) b);
}
//4.释放资源
socket.close();
ss.close();
}
}
运行结果:先运行服务器端,再运行客户端
练习2:接收和反馈
客户端:发送一条数据,接收服务端反馈的消息并打印
服务器:接收数据并打印,再给客户端反馈消息
客户端:
package a09tcpdemo;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;
public class Client2 {
public static void main(String[] args) throws IOException {
//1.创建Socket对象并连接服务器
Socket socket=new Socket("127.0.0.1",10001);
//2.写出数据
String str="鹿晗真帅";
OutputStream os = socket.getOutputStream();
os.write(str.getBytes());
//写一个结束标记
socket.shutdownOutput();
//3.接收服务端回写的数据
InputStream is = socket.getInputStream();
InputStreamReader isr=new InputStreamReader(is);
int b;
while((b=isr.read())!=-1){
System.out.print((char) b);
}
//释放资源
socket.close();
}
}
服务器:
package a09tcpdemo;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class Server2 {
public static void main(String[] args) throws IOException {
//1.创建对象并绑定端口
ServerSocket ss=new ServerSocket(10001);
//2.等待客户端连接
Socket socket = ss.accept();
//3.socket中获取输入流读取数据
InputStream is = socket.getInputStream();
InputStreamReader isr=new InputStreamReader(is);
int b;
//细节:
//read方法会从连接通道中读取数据
//但是需要有一个结束标记,此处的循环才会停止
//否则程序就会一直停在read方法这里,等待读取下面的数据
while((b=isr.read())!=-1){
System.out.print((char) b);
}
//4.回写数据
String str="是啊真的很帅";
OutputStream os = socket.getOutputStream();
os.write(str.getBytes());
//释放资源
socket.close();
ss.close();
}
}
运行结果:先运行服务器,再运行客户端
练习3:上传文件
客户端:将本地文件上传到服务器,接收服务器的反馈
服务器:接收客户端上传的文件,上传完毕之后给出反馈
客户端:
package a09tcpdemo;
import java.io.*;
import java.net.Socket;
public class Client3 {
public static void main(String[] args) throws IOException {
//1.创建Socket对象并连接服务器
Socket socket=new Socket("127.0.0.1",10001);
//2.读取本地文件中的数据,并写到服务器当中
BufferedInputStream bis=new BufferedInputStream(new FileInputStream("Test\\clientdir\\a.jpg"));
BufferedOutputStream bos=new BufferedOutputStream(socket.getOutputStream());
byte[] bytes=new byte[1024];
int len;
while((len=bis.read(bytes))!=-1){
bos.write(bytes,0,len);
bos.flush();
}
//往服务器写出结束标记
socket.shutdownOutput();
//3.接收服务器的回写数据
BufferedReader br=new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line = br.readLine();
System.out.println(line);
//4.释放资源
socket.close();
}
}
服务器端:
package a09tcpdemo;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class Server3 {
public static void main(String[] args) throws IOException {
//1.创建对象并绑定端口
ServerSocket ss=new ServerSocket(10001);
//2.等待客户端连接
Socket socket = ss.accept();
//3.读取数据并保存到本地文件中
BufferedInputStream bis=new BufferedInputStream(socket.getInputStream());
BufferedOutputStream bos=new BufferedOutputStream(new FileOutputStream("Test\\serverdir\\a.jpg"));
int len;
byte[] bytes=new byte[1024];
while((len=bis.read(bytes))!=-1){
bos.write(bytes,0,len);
bos.flush();
}
//4.回写数据
BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
bw.write("上传成功");
bw.newLine();
bw.flush();
//5.释放资源
socket.close();
ss.close();
}
}
运行结果:
练习4:上传文件(文件名重复问题)
解决上一题文件名重复问题
UUID类
用户端不用改和上面一样
package a09tcpdemo;
import java.io.*;
import java.net.Socket;
public class Client3 {
public static void main(String[] args) throws IOException {
//1.创建Socket对象并连接服务器
Socket socket=new Socket("127.0.0.1",10001);
//2.读取本地文件中的数据,并写到服务器当中
BufferedInputStream bis=new BufferedInputStream(new FileInputStream("Test\\clientdir\\a.jpg"));
BufferedOutputStream bos=new BufferedOutputStream(socket.getOutputStream());
byte[] bytes=new byte[1024];
int len;
while((len=bis.read(bytes))!=-1){
bos.write(bytes,0,len);
bos.flush();
}
//往服务器写出结束标记
socket.shutdownOutput();
//3.接收服务器的回写数据
BufferedReader br=new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line = br.readLine();
System.out.println(line);
//4.释放资源
socket.close();
}
}
服务器端
package a09tcpdemo;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.UUID;
public class Server3 {
public static void main(String[] args) throws IOException {
//1.创建对象并绑定端口
ServerSocket ss=new ServerSocket(10001);
//2.等待客户端连接
Socket socket = ss.accept();
//3.读取数据并保存到本地文件中
BufferedInputStream bis=new BufferedInputStream(socket.getInputStream());
String name= UUID.randomUUID().toString().replace("-","");
BufferedOutputStream bos=new BufferedOutputStream(new FileOutputStream("Test\\serverdir\\"+name+"a.jpg"));
int len;
byte[] bytes=new byte[1024];
while((len=bis.read(bytes))!=-1){
bos.write(bytes,0,len);
bos.flush();
}
//4.回写数据
BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
bw.write("上传成功");
bw.newLine();
bw.flush();
//5.释放资源
socket.close();
ss.close();
}
}
就会生成一个随机的名字
运行结果:
练习5:上传文件(多线程版)
想要服务器不停止,能接收很多用户上传的图片
提示:循环加多线程
多线程:
package a09tcpdemo;
import java.io.*;
import java.net.Socket;
import java.util.UUID;
public class MyRunnable implements Runnable{
Socket socket;
public MyRunnable(Socket socket){
this.socket=socket;
}
@Override
public void run() {
try {
//3.读取数据并保存到本地文件中
BufferedInputStream bis=new BufferedInputStream(socket.getInputStream());
String name= UUID.randomUUID().toString().replace("-","");
BufferedOutputStream bos=new BufferedOutputStream(new FileOutputStream("Test\\serverdir\\"+name+"a.jpg"));
int len;
byte[] bytes=new byte[1024];
while((len=bis.read(bytes))!=-1){
bos.write(bytes,0,len);
bos.flush();
}
//4.回写数据
BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
bw.write("上传成功");
bw.newLine();
bw.flush();
} catch (IOException e) {
throw new RuntimeException(e);
}finally{
//5.释放资源
if(socket!=null){
try {
socket.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
}
客户端:
package a09tcpdemo;
import java.io.*;
import java.net.Socket;
public class Client4 {
public static void main(String[] args) throws IOException {
//1.创建Socket对象并连接服务器
Socket socket=new Socket("127.0.0.1",10001);
//2.读取本地文件中的数据,并写到服务器当中
BufferedInputStream bis=new BufferedInputStream(new FileInputStream("Test\\clientdir\\a.jpg"));
BufferedOutputStream bos=new BufferedOutputStream(socket.getOutputStream());
byte[] bytes=new byte[1024];
int len;
while((len=bis.read(bytes))!=-1){
bos.write(bytes,0,len);
bos.flush();
}
//往服务器写出结束标记
socket.shutdownOutput();
//3.接收服务器的回写数据
BufferedReader br=new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line = br.readLine();
System.out.println(line);
//4.释放资源
socket.close();
}
}
服务器端:
package a09tcpdemo;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.UUID;
public class Server4 {
public static void main(String[] args) throws IOException {
//1.创建对象并绑定端口
ServerSocket ss=new ServerSocket(10001);
while (true) {
//2.等待客户端连接
Socket socket = ss.accept();
//有一个客户端连接就开启一条线程
new Thread(new MyRunnable(socket)).start();
}
}
}
运行结果:运行4次运行结果:
练习6:上传文件(线程池优化)
频繁创建线程并销毁非常浪费系统资源,所以需要用线程池优化
线程:
package a09tcpdemo;
import java.io.*;
import java.net.Socket;
import java.util.UUID;
public class MyRunnable1 implements Runnable{
Socket socket;
public MyRunnable1(Socket socket){
this.socket=socket;
}
@Override
public void run() {
try {
//3.读取数据并保存到本地文件中
BufferedInputStream bis=new BufferedInputStream(socket.getInputStream());
String name= UUID.randomUUID().toString().replace("-","");
BufferedOutputStream bos=new BufferedOutputStream(new FileOutputStream("Test\\serverdir\\"+name+"a.jpg"));
int len;
byte[] bytes=new byte[1024];
while((len=bis.read(bytes))!=-1){
bos.write(bytes,0,len);
bos.flush();
}
//4.回写数据
BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
bw.write("上传成功");
bw.newLine();
bw.flush();
} catch (IOException e) {
throw new RuntimeException(e);
}finally{
//5.释放资源
if(socket!=null){
try {
socket.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
}
用户端:
package a09tcpdemo;
import java.io.*;
import java.net.Socket;
public class Client5 {
public static void main(String[] args) throws IOException {
//1.创建Socket对象并连接服务器
Socket socket=new Socket("127.0.0.1",10001);
//2.读取本地文件中的数据,并写到服务器当中
BufferedInputStream bis=new BufferedInputStream(new FileInputStream("Test\\clientdir\\a.jpg"));
BufferedOutputStream bos=new BufferedOutputStream(socket.getOutputStream());
byte[] bytes=new byte[1024];
int len;
while((len=bis.read(bytes))!=-1){
bos.write(bytes,0,len);
bos.flush();
}
//往服务器写出结束标记
socket.shutdownOutput();
//3.接收服务器的回写数据
BufferedReader br=new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line = br.readLine();
System.out.println(line);
//4.释放资源
socket.close();
}
}
服务器端
package a09tcpdemo;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class Server5 {
public static void main(String[] args) throws IOException {
//创建线程池对象
ThreadPoolExecutor pool=new ThreadPoolExecutor(
3,//核心线程数量
16,//线程池总大小
60,//空闲时间
TimeUnit.SECONDS,//空闲时间(单位)
new ArrayBlockingQueue<>(2),//队列
Executors.defaultThreadFactory(),//线程工厂,让线程池如何创建线程对象
new ThreadPoolExecutor.AbortPolicy()//阻塞队列
);
//1.创建对象并绑定端口
ServerSocket ss=new ServerSocket(10001);
while (true) {
//2.等待客户端连接
Socket socket = ss.accept();
//有一个客户端连接就开启一条线程
// new Thread(new MyRunnable1(socket)).start();
pool.submit(new MyRunnable1(socket));
}
}
}
运行结果:运行4次结果
练习7:BS接收浏览器的消息并打印
客户端:不需要写
服务器:接收数据并打印
package a09tcpdemo;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
public static void main(String[] args) throws IOException {
//TCP协议接收数据
//1.创建对象ServerSocket
ServerSocket ss=new ServerSocket(10001);
//2.监听客户端的连接
Socket socket = ss.accept();
//3.从连接通道中获取输入流读取数据
/* InputStream is = socket.getInputStream();
InputStreamReader isr=new InputStreamReader(is);//将字节流转成字符流
BufferedReader br=new BufferedReader(isr);//提高效率
*/
BufferedReader br=new BufferedReader(new InputStreamReader(socket.getInputStream()));
int b;
while((b=br.read())!=-1){
System.out.print((char)b);
}
//4.释放资源
socket.close();//断开与客户端连接
ss.close();//关闭服务器
}
}
运行时: 在浏览器输入127.0.0.1:10001
然后按回车
控制台就会打印如下信息