实现一个聊天的案例,使用多线程和心跳包。当服务器断开的时候,客户端会自动尝试重新连接,当服务器开启的时候,客户端会自动连接
Server服务器类
package Demo3_Chat;
import com.sun.source.tree.Scope;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.security.spec.ECField;
import java.util.Scanner;
public class Server {
public static void main(String[] args) {
System.out.println("服务器已在运行....");
try {
ServerSocket serverSocket = new ServerSocket(8888);
while(true){
Socket socket = serverSocket.accept();
new Thread(new Server_listen(socket)).start();
new Thread(new Server_send(socket)).start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
class Server_listen implements Runnable{
private Socket socket;
Server_listen(Socket socket){
this.socket = socket;
}
@Override
public void run() {
try {
InputStream is = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(is,"UTF-8");
while(true){
int len = 0;
char[] charArr = new char[1024];
while((len = isr.read(charArr)) != -1){
System.out.println(new String(charArr,0,len));
}
}
} catch (IOException e) {
e.printStackTrace();
}finally{
try{
socket.close();
}catch (Exception e){
e.printStackTrace();
}
}
}
}
class Server_send implements Runnable{
private Socket socket;
Server_send(Socket socket){
this.socket = socket;
}
@Override
public void run() {
try{
OutputStream os = socket.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(os,"UTF-8");
Scanner sc = new Scanner(System.in);
while(true){
System.out.print("请输入要发送的内容:");
String str = sc.nextLine();
osw.write(str);
osw.flush();
}
}catch (Exception e){
e.printStackTrace();
}
}
}
Client客户端类
package Demo3_Chat;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.util.Scanner;
public class Client {
private static Socket socket;
public static boolean connection_state = false;
private static OutputStreamWriter osw;
public static void main(String[] args) {
while(!connection_state){
connect();
try{
Thread.sleep(3000);
}catch (Exception e){
e.printStackTrace();
}
}
}
public static void connect(){
try{
socket = new Socket("127.0.0.1",8888);
connection_state = true;
OutputStreamWriter osw = new OutputStreamWriter(socket.getOutputStream(),"UTF-8");
new Thread(new Client_listen(socket)).start();
new Thread(new Client_send(socket,osw)).start();
new Thread(new Client_heart(socket,osw)).start();
}catch (Exception e){
e.printStackTrace();
connection_state = false;
}
}
//自动重连机制
public static void reconnect(){
while(!connection_state){
System.out.println("正在尝试重新连接.....");
connect();
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class Client_listen implements Runnable{
private Socket socket;
Client_listen(Socket socket){
this.socket = socket;
}
@Override
public void run() {
try{
InputStream is = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(is,"UTF-8");
while(true){
int len = 0;
char[] charArr = new char[1024];
while((len = isr.read(charArr)) != -1){
System.out.println(new String(charArr,0,len));
}
}
}catch (Exception e){
e.printStackTrace();
}
}
}
class Client_send implements Runnable{
private Socket socket;
private OutputStreamWriter osw;
Client_send(Socket socket,OutputStreamWriter osw){
this.socket = socket;
this.osw = osw;
}
@Override
public void run(){
try{
Scanner sc = new Scanner(System.in);
while(true){
System.out.print("请输入要发送的内容:");
String str = sc.nextLine();
osw.write(str);
osw.flush();
}
}catch (Exception e){
e.printStackTrace();
try{
socket.close();
Client.connection_state = false;
Client.reconnect();
}catch (Exception e2){
e2.printStackTrace();
}
}
}
}
//心跳包机制
class Client_heart implements Runnable{
private Socket socket;
private OutputStreamWriter osw;
Client_heart(Socket socket,OutputStreamWriter osw){
this.socket = socket;
this.osw = osw;
}
@Override
public void run() {
try{
System.out.println("心跳包线程已启动");
while(true){
Thread.sleep(5000);
osw.write("*****心跳包*****");
osw.flush();
}
}catch (Exception e){
e.printStackTrace();
try{
socket.close();
Client.connection_state = false;
Client.reconnect();
}catch (Exception e2){
e2.printStackTrace();
}
}
}
}
断线重新连接部分代码
//自动重连机制
public static void reconnect(){
while(!connection_state){
System.out.println("正在尝试重新连接.....");
connect();
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
心跳包类
//心跳包机制
class Client_heart implements Runnable{
private Socket socket;
private OutputStreamWriter osw;
Client_heart(Socket socket,OutputStreamWriter osw){
this.socket = socket;
this.osw = osw;
}
@Override
public void run() {
try{
System.out.println("心跳包线程已启动");
while(true){
Thread.sleep(5000);
osw.write("*****心跳包*****");
osw.flush();
}
}catch (Exception e){
e.printStackTrace();
try{
socket.close();
Client.connection_state = false;
Client.reconnect();
}catch (Exception e2){
e2.printStackTrace();
}
}
}
}
心跳包实现截图
这里把心跳包输出出来是为了方便查看心跳包是否构建成功
断线重连实现截图
正常状态下
当服务器关闭后
当服务器重启
重新启动服务器后,服务器和客户端又可以继续进行聊天了,客户端会一直等待服务器的开启。