前言
Java网络编程(2)Socket 前面对Socket有了一定的了解,仅仅完成了发送一次信息就关闭的通信,现在写一个可以多次通话的聊天系统
目录
- 思考
- 可持续读写
- 多线程读写
- 相互通信
- 总结
思考
前面发送了信息就关闭了Socket,显然不符合平常的聊天系统,还需要改进一下
可持续读写
服务器:
package com.company.NewThread;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
public class NewSocketServer {
public static void main(String[] args) throws IOException {
//serverSocket等待连接
ServerSocket serverSocket=new ServerSocket(55555);
//接受连接,创建socket
Socket socket=serverSocket.accept();
System.out.println("IP地址:"+socket.getLocalAddress());
//输出流
BufferedReader reader=new BufferedReader(new InputStreamReader(socket.getInputStream(),"UTF-8"));
String str;
while ((str=reader.readLine())!=null){
System.out.println(str);
}
reader.close();
socket.close();
serverSocket.close();
}
}
客户端:
package com.company.NewThread;
import java.io.*;
import java.net.Socket;
import java.util.Scanner;
public class NewSocketClient {
public static void main(String[] args) throws IOException {
//发送连接请求
Socket socket=new Socket("127.0.0.1",55555);
//输入流
BufferedReader reader=new BufferedReader(new InputStreamReader(System.in,"UTF-8"));
//往socket中写入信息
BufferedWriter writer=new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(),("UTF-8")));
//保持通话
while (true){
String str=reader.readLine();
writer.write(str);
writer.write("\n");
//刷新缓存区
writer.flush();
}
}
}
服务器:
客户端:
通过一个while循环实现可持续的读写,客户端发送的\n换行,服务器仅读一行就可以多次接收信息
多线程读写
要是多个客户端往服务器发送消息会阻塞
因为Socket通信是阻塞式的,一个客户端发送的信息会等到while循环结束才会接收另一个客户端的信息
新客户端A:
package com.company.NewThread;
import java.io.*;
import java.net.Socket;
public class ClientA {
public static void main(String[] args) throws IOException {
//发送连接请求
Socket socket=new Socket("127.0.0.1",55555);
//输入流
BufferedReader reader=new BufferedReader(new InputStreamReader(System.in,"UTF-8"));
//往socket中写入信息
BufferedWriter writer=new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(),("UTF-8")));
//保持通话
while (true){
String str=reader.readLine();
writer.write(str);
writer.write("\n");
//刷新缓存区
writer.flush();
}
}
}
在NewScoketClient没有断开连接,ClientA都无法连接
通过多线程解决:
服务器:
package com.company.NewThread;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadServer {
public static void main(String[] args) throws IOException {
//serverSocket等待连接
ServerSocket serverSocket=new ServerSocket(55555);
//创建线程池:限定最多50个线程
ExecutorService executor= Executors.newFixedThreadPool(50);
while (true) {
//接受连接,创建socket
Socket socket = serverSocket.accept();
System.out.println("IP地址:" + socket.getLocalAddress());
//线程
Runnable runnable=()->{
try {
BufferedReader reader=new BufferedReader(new InputStreamReader(socket.getInputStream(),"UTF-8"));
String str=null;
while ((str=reader.readLine())!=null){
System.out.println(str);
}
} catch (IOException e) {
e.printStackTrace();
}
};
executor.submit(runnable);
}
}
}
客户端不变
记得给客户端改一下输入
服务器的作用完成了,如果两个客户端想要交流怎么解决?
相互通信
创建一个读写线程就可以
SocketWriter:
package com.company.ThreadSocket;
import java.io.*;
import java.net.Socket;
import java.util.Scanner;
public class SocketWriter extends Thread {
private Socket socket = null;
private BufferedWriter writer = null;
private BufferedReader reader = null;
public SocketWriter(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
try {
while (true) {
writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(),"UTF-8"));
reader=new BufferedReader(new InputStreamReader(System.in,"UTF-8"));
String str=null;
if ((str=reader.readLine())!=null) {
writer.write("Socekt:"+str);
writer.write("\n");
writer.flush();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
SocketReader:
package com.company.ThreadSocket;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
public class SocketReader extends Thread {
private Socket socket = null;
private BufferedReader reader = null;
public SocketReader(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
try {
while (true) {
reader = new BufferedReader(new InputStreamReader(socket.getInputStream(),"UTF-8"));
System.out.println(reader.readLine());
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
SocketServer:
package com.company.ThreadSocket;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class SocketServer {
public static void main(String[] args) {
try {
//1、创建一个服务端
ServerSocket serverSocket = new ServerSocket(8888);
//2、接受客户端的连接
Socket socket = serverSocket.accept();
System.out.println(socket);
//3、服务端启动读取线程和写入线程
new SocketWriter(socket).start();
new SocketReader(socket).start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
SocketClient:
package com.company.ThreadSocket;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
public class SocketClient {
public static void main(String[] args){
try {
//1、根据IP和端口号创建一个客户端
Socket socket=new Socket("127.0.0.1",8888);
//2、启动读取和写入线程
new SocketReader(socket).start();
new SocketWriter(socket).start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
创建了四个类:读进程、写进程、服务器、客户端
服务器、客户端通过调用读写进程完成相互通信
总结
- 上一章完成了简单的通信,这一章是加强版通信
- 持续通信通过一个while循环实现
- 多线程通信通过线程池实现
- 相互通信通过一个读写进程实现