1、实现:实现服务端与客户端一对多的关系;服务端关闭则客户端等待服务端启动后重连,客户端关闭则服务端关闭与服务端的socket连接,如果所有客户端关闭,则服务端等待客户端连接。
实现客户端向服务端单向发送数据(服务端向客户端发送数据同理)。
2、服务端:
A、服务器端创建ServerSocket,循环调用accept()等待客户端连接
B、客户端创建一个socket并请求和服务器端连接
C、服务器端接受客户端请求,创建socket与该客户建立专线连接
D、建立连接的两个socket在一个单独的线程上对话
E、服务器端继续等待新的连接
代码:
import java.io.IOException; import java.io.ObjectInputStream; import java.net.ServerSocket; import java.net.Socket; import java.util.Iterator; import java.util.Map; import java.util.Map.Entry; import java.util.concurrent.ConcurrentHashMap; public class SocketServer { private static ServerSocket serverSocket = null; private static Map<String, ModelClass> info = new ConcurrentHashMap<>(); static { try { serverSocket = new ServerSocket(9090); } catch (IOException e) { System.out.println("create serverSocket error: " + e.getMessage()); } } public static void main(String[] args) throws IOException { // 定时打印接收到的数据 new Thread(new Runnable( ) { @Override public void run() { while (true) { Iterator<Map.Entry<String, ModelClass>> it = info.entrySet().iterator(); while(it.hasNext()) { Entry<String, ModelClass> entry = it.next(); ModelClass mc = entry.getValue(); System.out.println(mc.name); System.out.println(mc.m1.get(0)); System.out.println(mc.m2.get(0).value); System.out.println(); } try { Thread.sleep(5000); } catch (InterruptedException e) { System.out.println(e.getMessage()); } } } }).start(); // 等待客户端连接 new Thread(new Runnable() { @Override public void run() { while (true) { try { System.out.println("*****服务器已启动,等待客户端连接*****"); Socket socket = serverSocket.accept(); System.out.println("*****已连接客户端*****"); new SST(socket).start(); } catch (Exception e) { System.out.println("socket accept error: " + e.getMessage()); } } } }).start(); } static class SST extends Thread { private Socket socket; private String key; public SST(Socket socket) { this.socket = socket; key = socket.getInetAddress().toString() + "/" + socket.getPort(); } @Override public void run() { // BufferedReader br = null; // 读取客户端输入的文件流 ObjectInputStream ois = null; // 读取客户端输入的对象流 try { while (true) { // br = new BufferedReader(new InputStreamReader(socket.getInputStream())); // String msg = null; // while((msg = br.readLine()) != null) { // System.out.println("get msg---" + socket.getInetAddress() + "/" + socket.getPort()); // System.out.println("client msg: " + msg); // } ois = new ObjectInputStream(socket.getInputStream()); Object obj = ois.readObject(); ModelClass mc = (ModelClass)obj; info.put(key, mc); } } catch (Exception e) { System.out.println("get msg error: " + e.getMessage()); } finally { if (info.containsKey(key)) { info.remove(key); } try { // if (br != null) { // br.close(); // } if (ois != null) { ois.close(); } } catch (IOException e) { System.out.println("br close error: " + e.getMessage()); } finally { if (socket != null) { try { socket.close(); } catch (IOException e) { System.out.println(e.getMessage()); } } } } } } }
3、客户端:
A、用服务器的IP地址和端口号实例化Socket对象。
B、获得Socket上的流,以进行读写。
C、关闭打开的流和Socket。
代码:
import java.io.ObjectOutputStream; import java.net.Socket; public class SocketClient { ModelClass mc; public SocketClient() { new Thread(new Runnable() { @Override public void run() { try { client(); } catch (Exception e) { System.out.println(e.getMessage()); } } }).start(); } public void send(ModelClass mc) { this.mc = mc; } private void client() throws Exception { Socket socket = null; ObjectOutputStream oos = null; try { while(true) { System.out.println("create new socket!"); try { socket = new Socket("127.0.0.1", 9090); while (true) { if (mc == null) { Thread.sleep(1000); continue; } System.out.println("out object!"); oos = new ObjectOutputStream(socket.getOutputStream()); oos.writeObject(mc); mc = null; } } catch (Exception e) { System.out.println("socket error: " + e.getMessage()); } Thread.sleep(5000); } } finally { if (socket != null) { socket.close(); } if (oos != null) { oos.close(); } } } }
4、客户端实例:
import socket.ModelClass.InnerModel; import socket.ModelClass.Status; public class Client2 { private static SocketClient client; public static void main(String[] args) throws Exception { client = new SocketClient(); new Client2().func(); } public void func() throws InterruptedException { ModelClass mc = new ModelClass(); mc.name = "client2"; mc.m1.add(Status.NA); mc.m2.clear(); InnerModel im = new InnerModel(); while(true) { im.value = "client2: " + System.currentTimeMillis(); mc.m2.add(im); client.send(mc); Thread.sleep(2000); } } }
5、对象model:
import java.io.Serializable; import java.util.ArrayList; import java.util.List; public class ModelClass implements Serializable { private static final long serialVersionUID = 1000L; String name; List<Status> m1 = new ArrayList<>(); List<InnerModel> m2 = new ArrayList<>(); static class InnerModel implements Serializable { private static final long serialVersionUID = 1001L; String value; } public enum Status { OK, ERROR, NA, WARNING, FATAL; } }