先上运行截图
1,运行服务端:
2,运行客户端,与服务端建立连接:
3,连接成功,发送消息:
4,客户端向服务端定期发送心跳包保持连通性:
接下来上代码:
1,服务端
package socket.ab;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
public class Server {
//创建集合对象
public static List<MyChannel> list=new ArrayList<MyChannel>();
public static void main(String[] args) {
try {
System.out.println("服务器开始运行");
ServerSocket serverSocket=new ServerSocket(8080);
while(true) {
Socket socket=serverSocket.accept();//接收客户请求
//一个客户机与服务器通信
//new Thread(new Listen(socket)).start();
//new Thread(new Send(socket)).start();
//服务器用于交换消息,创建线程类对象
MyChannel channel=new MyChannel(socket);
//添加到集合
list.add(channel);
if(list != null) {
System.out.println("服务器收到"+channel+"连接");
}
new Thread(channel).start();
}
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
}
2,集合对象
package socket.ab;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.util.List;
public class MyChannel implements Runnable{
private Socket socket;
private boolean flag=true;
private ObjectInputStream ois;
private ObjectOutputStream oos;
//初始化
public MyChannel(Socket socket){
this.socket=socket;
try {
ois=new ObjectInputStream(socket.getInputStream());//获取输入流
oos=new ObjectOutputStream(socket.getOutputStream());//获取输出流
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
flag=false;
try {
socket.close();
} catch (IOException e1) {
// TODO 自动生成的 catch 块
e1.printStackTrace();
}
}
}
//接收数据方法
private String receive(){
String str="";
try {
str=ois.readUTF();
if(str.equals("我是心跳包")) {
System.out.println(str);
}
} catch (IOException e) {
System.out.println("断开连接");
flag=false;
try {
socket.close();
} catch (IOException e1) {
Server.list.remove(this);
}
}
return str;
}
//发送数据方法
private void send(String str) {
if(str!=null&&str.length()!=0) {
if(!str.equals("我是心跳包")) {
try {
oos.writeUTF(str);
oos.flush();
} catch (IOException e) {
flag=false;
try {
socket.close();
// Server.list.remove(this);
} catch (IOException e1) {
// Server.list.remove(this);
}
}
}
}
}
//转发
private void sendOther() {
String str=this.receive();
List<MyChannel> list=Server.list;
if(list.size()>1) {
for(MyChannel other :list) {
if(other==this) {
continue;//不发给自己
}
other.send(str);
}
}
}
@Override
public void run() {
// TODO 自动生成的方法存根
while(flag) {
//this.send(receive());
sendOther();
}
}
}
3,send方法
package socket.ab;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.util.Scanner;
public class Send implements Runnable{
private Socket socket;
private ObjectOutputStream oos;
public static String name="";
Send(Socket socket,String name,ObjectOutputStream oos){
this.socket=socket;
Send.name=name;
this.oos=oos;
}
String str="";
@Override
public void run() {
// TODO 自动生成的方法存根
try {
while(true) {
Thread.sleep(1000);
oos.writeUTF(Frame.text);
oos.flush();
Frame.text="";
}
} catch (IOException | InterruptedException e) {
System.out.println("发送失败");
}
}
}
4,listen方法
package socket.ab;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.net.Socket;
public class Listen implements Runnable{
private Socket socket;
//初始化
Listen(Socket socket){
this.socket=socket;
}
@Override
public void run() {
// TODO 自动生成的方法存根
try {
//获取输入流
ObjectInputStream ois=new ObjectInputStream(socket.getInputStream());
while(true) {
String read=ois.readUTF();
Frame.jtx.append(Frame.date()+"\n"+"收到"+read+"\n");
// System.out.println("收到"+ois.readUTF());
}
} catch (IOException e) {
System.out.println("接收失败");
Client.connet_state=false;
Client.reconnet();
}finally {
try {
socket.close();
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
}
}
5,客户端
package socket.ab;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
public class Client {
private static Socket socket;
private static ObjectOutputStream oos;
public static boolean connet_state=false;
public static String name=Frame.tit;
// static String[] arrays=new String[5];
public static void main(String[] args) {
new Frame();
System.out.println(name+"连接到服务器");
connet();
if(connet_state) {
try {
oos=new ObjectOutputStream(socket.getOutputStream());
new Thread(new Listen(getSocket())).start();
new Thread(new Send(getSocket(),name,oos)).start();
new Thread(new HeartBeat(getSocket(),oos)).start();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
private static void connet() {
try {
setSocket(new Socket("127.0.0.1",8080));
connet_state=true;
} catch (UnknownHostException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
connet_state=false;
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
connet_state=false;
}
}
public static void reconnet() {
while(!connet_state) {
System.out.println("尝试重新连接...");
try {
connet();
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(connet_state) {
try {
oos=new ObjectOutputStream(socket.getOutputStream());
new Thread(new Listen(getSocket())).start();
new Thread(new Send(getSocket(),name,oos)).start();
new Thread(new HeartBeat(getSocket(),oos)).start();
System.out.println("重连成功");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public static Socket getSocket() {
return socket;
}
public static void setSocket(Socket socket) {
Client.socket = socket;
}
}
6,界面显示
package socket.ab;
import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.FlowLayout;
import java.awt.Panel;
import java.awt.TextField;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Random;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.ScrollPaneConstants;
public class Frame extends java.awt.Frame implements Runnable{
public static JTextArea jtx=new JTextArea(200,150);
public static TextField tf=new TextField(30);
public Frame() {
initFrame();
initEventListner();
}
public static String text="";
public static String tit="用户"+new Random().nextInt(900)+100;
public static String tit2=tit;
// public static String getTit() {
// return tit;
// }
public static boolean sendflag=true;
// public static String getText() {
// return text;
// }
private void initFrame() {
setTitle(tit);
setSize(600, 500);
setLocation(new Random().nextInt(500)+100, new Random().nextInt(900)+100);
setResizable(false);
Panel p=new Panel();
setLayout(new BorderLayout());
//滚动条
JScrollPane j=new JScrollPane();
j.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
j.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
// JTextArea jtx=new JTextArea(200,150);
jtx.setFocusable(false);
j.setViewportView(jtx);
add(j,BorderLayout.CENTER);
p.setLayout(new FlowLayout());
add(p,BorderLayout.SOUTH);
Button btn=new Button("发送");
tf.requestFocus();
p.add(tf);
p.add(btn);
btn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// TODO 自动生成的方法存根
// if(text!=null && !text.trim().equals("")) {
text=Send.name+":"+tf.getText();
jtx.append(date()+"\n");
jtx.append("我发送了:"+tf.getText()+"\n");
sendflag=true;
tf.setText("");
// }
}
});
setVisible(true);
repaint();
}
public static String date() {
Date time=new Date();
SimpleDateFormat format=new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
return "----------"+format.format(time);
}
private void initEventListner() {
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
}
@Override
public void run() {
// TODO 自动生成的方法存根
new Frame();
}
}
7,心跳包测试
package socket.ab;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.net.Socket;
public class HeartBeat implements Runnable{
private Socket socket;
private ObjectOutputStream oos;
public static String heart="我是心跳包";
public HeartBeat(Socket socket,ObjectOutputStream oos){
this.socket=socket;
this.oos=oos;
}
@Override
public void run() {
// TODO Auto-generated method stub
System.out.println("心跳包线程已启动...");
try {
while(true) {
Thread.sleep(5000);
oos.writeUTF(heart);
// oos.flush();
}
} catch (InterruptedException | IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Client.connet_state=false;
Client.reconnet();
}
}
}
点赞支持一下吧~