一。客户端和服务端
服务端 (创建一端,连接另一端,开启线程)
/*sockte服务器*/
public class Server {
public static void main(String[] args) throws Exception {
//1.创建socket服务端
ServerSocket serverSocket = new ServerSocket(9999);
while (true){
//2.连接客户端
Socket socket = serverSocket.accept();
//3.开启两个线程
new Thread(new Server_Lister(socket)).start();
new Thread(new Server_Send(socket)).start();
}
}
}
客户端 (创建一端,连接另一端,开启线程)
public class Client {
private static Socket socket;
private static boolean connection_status = false;
/*1.创建客户端 2.连接服务器*/
private static void connect(){
try {
socket = new Socket("localhost",9999);
connection_status = true;
} catch (IOException e) {
e.printStackTrace();
connection_status = false;
}
}
public static void main(String[] args) {
//1.创建客户端 2.连接服务器
connect();
if (connection_status){
//3.开启两个线程
new Thread(new Client_Listen(socket)).start();
new Thread(new Client_Send(socket)).start();
}
}
}
二。四个线程(服务端的发送接收线程,客户端的发送接收线程)
1.服务端发送线程
public class Server_Send implements Runnable {
private Socket socket;
public Server_Send(Socket socket){
this.socket = socket;
}
@Override
public void run() {
System.out.println("进入服务端的发送线程");
try {
ObjectOutputStream objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
Scanner scanner = new Scanner(System.in);
while (true){
System.out.println("请输入要发送的消息");
String msg = scanner.nextLine();
JSONObject jsonObject = new JSONObject();
jsonObject.put("type","chat");
jsonObject.put("msg",msg);
objectOutputStream.writeObject(jsonObject);
//刷新缓冲区
objectOutputStream.flush();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
2.客户端发送线程
public class Client_Send implements Runnable {
private Socket socket;
Client_Send(Socket socket){
this.socket = socket;
}
@Override
public void run() {
System.out.println("进入客户端的发送线程");
try {
ObjectOutputStream objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
Scanner scanner = new Scanner(System.in);
while (true){
System.out.print("请输入要发送的消息");
String msg = scanner.nextLine();
JSONObject jsonObject = new JSONObject();
jsonObject.put("type","chat");
jsonObject.put("msg",msg);
objectOutputStream.writeObject(jsonObject);
//刷新缓冲区
objectOutputStream.flush();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
3.服务端接收消息线程
public class Server_Lister implements Runnable {
private Socket socket;
public Server_Lister(Socket socket){
this.socket = socket;
}
@Override
public void run() {
ObjectInputStream objectInputStream = null;
try {
objectInputStream = new ObjectInputStream(socket.getInputStream());
while (true){
System.out.println(objectInputStream.readObject());
}
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
4.客户端接收消息线程
public class Client_Listen implements Runnable {
private Socket socket;
Client_Listen(Socket socket){
this.socket = socket;
}
@Override
public void run() {
System.out.println("进入客户端的接收线程");
ObjectInputStream objectInputStream = null;
try {
objectInputStream = new ObjectInputStream(socket.getInputStream());
while (true){
System.out.println(objectInputStream.readObject());
}
} catch ( Exception e) {
e.printStackTrace();
}
}
}
三。心跳包
为了防止连接断开,让客户端不停地定期给服务端发送心跳包;——相当于再写一个客户端发送消息的线程(不断发送)
一旦心跳包发送失败,就需要重新连接 ——重新连接
由于在一个socket下只能有一个outPutStream,所以不能在两个线程分别new出来,所以需要声明公共
属性objectOutputStream(线程类和客户端类都声明,客户端类赋值–调用构造函数,线程类接收值–写构造函数)
1.客户端发送心跳包(相当于客户端发送线程)
//1.客户端发送心跳线程
public class Client_Heart implements Runnable {
private Socket socket;
private ObjectOutputStream objectOutputStream;
Client_Heart(Socket socket,ObjectOutputStream objectOutputStream){
this.socket = socket;
this.objectOutputStream = objectOutputStream;
}
@Override
public void run() {
System.out.println("进入心跳包线程");
try {
while (true){
Thread.sleep(5000);
JSONObject jsonObject = new JSONObject();
jsonObject.put("type","heart");
jsonObject.put("msg","心跳包");
objectOutputStream.writeObject(jsonObject);
objectOutputStream.flush();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
2.重新连接机制
a.客户端添加重新连接方法
b.在没有连接地方使用重新连接方法
/*重新连接*/
public static void reconnect(){
while (!connection_status){
System.out.println("正在尝试重新连接");
connect();
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}