以J2SDK-1.3为例,Socket和ServerSocket类库位于java.net包中。ServerSocket用于服务器端,Socket是建立网络连接时使用的。在连接成功时,应用程序两端都会产生一个Socket实例,操作这个实例,完成所需的会话。对于一个网络连接来说,套接字是平等的,并没有差别,不因为在服务器端或在客户端而产生不同级别。不管是Socket还是ServerSocket它们的工作都是通过SocketImpl类及其子类完成的。
一个非常简单的java聊天程序,有客户端和服务器端,目前只有群聊功能,其他的所有功能都可以在这个基础上添加,现在我分享出来主要是为了保持一个最简单的java聊天程序便于初学者学习,界面也非常的简洁,只有两个文件,主要是用了socket,java多线程,知识点不是很多,很适合初学者
服务器端程序:
import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.io.*; import java.net.ServerSocket; import java.net.Socket; import java.net.SocketException; import java.util.HashMap; import java.util.Map; import java.util.Set; /** * @Auther: 李景然 * @Date: 2018/5/17 10:12 * @Description: */ public class TKServer extends JFrame implements ActionListener { private Map<Integer, Socket> clients = new HashMap<Integer, Socket>(); private JTextArea msg = new JTextArea("服务器消息接收器 "); private JTextArea input = new JTextArea(); private JButton msgSend = new JButton("发送群消息"); public TKServer() { // TODO Auto-generated constructor stub this.setVisible(true); this.setTitle("服务器"); this.setSize(550, 750); this.setResizable(true); this.setLayout(new FlowLayout()); this.addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent arg0) { // TODO Auto-generated method stub super.windowClosing(arg0); System.exit(0); } }); input.setColumns(40); input.setRows(5); input.setAutoscrolls(true); msgSend.addActionListener(this); msgSend.setActionCommand("sendMsg"); msg.setAutoscrolls(true); msg.setColumns(40); msg.setRows(30); JScrollPane spanel = new JScrollPane(msg); JScrollPane editpanel = new JScrollPane(input); this.add(spanel); this.add(editpanel); this.add(msgSend); } public static void main(String[] args) { new TKServer().listenClient(); } public void listenClient() { String temp = ""; try { //server尝试接收其他Socket的连接请求,server的accept方法是阻塞式的 // 定义一个ServerSocket监听在端口8899上 ServerSocket server = new ServerSocket(8899); while (true) { System.out.println("服务器端正在监听"); Socket socket = server.accept(); clients.put(socket.getPort(), socket); temp = "客户端" + socket.getPort() + " 连接"; this.apppendMsg(temp); new mythread(socket, this).start(); } } catch (Exception e) { // TODO: handle exception e.printStackTrace(); } } public void apppendMsg(String msg) { this.msg.append(msg + " "); } public void sendMsgToAll(Socket fromSocket, String msg) { Set<Integer> keset = this.clients.keySet(); java.util.Iterator<Integer> iter = keset.iterator(); while (iter.hasNext()) { int key = iter.next(); Socket socket = clients.get(key); if (socket != fromSocket) { try { if (socket.isClosed() == false) { if (socket.isOutputShutdown() == false) { Writer writer = new OutputStreamWriter( socket.getOutputStream()); writer.write(msg); writer.flush(); } } } catch (SocketException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } catch (IOException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } } } } @Override public void actionPerformed(ActionEvent e) { // TODO Auto-generated method stub String temp = ""; if ("sendMsg".equals(e.getActionCommand())) { if ((temp = this.input.getText()) != null) { System.out.println("开始向客户端群发消息"); this.apppendMsg("服务器-->" + temp); Set<Integer> keset = this.clients.keySet(); java.util.Iterator<Integer> iter = keset.iterator(); while (iter.hasNext()) { int key = iter.next(); Socket socket = clients.get(key); try { Writer writer = new OutputStreamWriter(socket.getOutputStream()); writer.write(temp); writer.flush(); } catch (SocketException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } catch (IOException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } } this.input.setText(""); } } } } class mythread extends Thread { private Socket socket = null; private TKServer server = null; private InputStreamReader reader = null; char chars[] = new char[64]; int len; private String temp = null; public mythread(Socket socket, TKServer server) { // TODO Auto-generated constructor stub this.socket = socket; this.server = server; init(); } private void init() { try { reader = new InputStreamReader(socket.getInputStream()); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } @Override public void run() { // TODO Auto-generated method stub System.out.println("子线程开始工作"); while (true) { try { System.out.println("服务器 线程" + this.getId() + "-->开始从客户端读取数据——>"); while ((len = ((Reader) reader).read(chars)) != -1) { temp = new String(chars, 0, len); System.out.println("客户端" + socket.getPort() + "说-->" + temp); server.apppendMsg("客户端" + socket.getPort() + "说-->" + temp); server.sendMsgToAll(this.socket, "客户端" + socket.getPort() + "说-->" + temp); } if (socket.getKeepAlive() == false) { ((Reader) reader).close(); temp = "客户端" + socket.getPort() + "-->退出"; server.apppendMsg(temp); socket.close(); this.stop(); } } catch (Exception e) { // TODO: handle exception e.printStackTrace(); try { ((Reader) reader).close(); socket.close(); } catch (IOException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } } } } }
客户端程序:
/** * @Auther: 李景然 * @Date: 2018/5/17 10:15 * @Description: */ import java.awt.FlowLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.Reader; import java.io.Writer; import java.net.Socket; import java.net.UnknownHostException; import javax.swing.*; public class TKClient extends JFrame implements ActionListener { // 为了简单起见,所有的异常都直接往外抛 String host = "127.0.0.1"; // 要连接的服务端IP地址 int port = 8899; // 要连接的服务端对应的监听端口 mythread thread = null; Socket client = null; Writer writer = null; private JTextArea msg = new JTextArea("客户端消息接收器 "); private JTextArea input = new JTextArea(); private JButton msgSend = new JButton("发送群消息"); public TKClient() { // TODO Auto-generated constructor stub initSocket(); this.setVisible(true); this.setTitle("客户端"); this.setSize(550, 750); this.setResizable(true); this.setLayout(new FlowLayout()); this.addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent arg0) { // TODO Auto-generated method stub super.windowClosing(arg0); try { if (client != null) { client.close(); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } if (thread != null) { thread.stop(); } System.exit(0); } }); input.setColumns(40); input.setRows(10); input.setAutoscrolls(true); msgSend.addActionListener(this); msgSend.setActionCommand("sendMsg"); msg.setAutoscrolls(true); msg.setColumns(40); msg.setRows(25); JScrollPane spanel = new JScrollPane(msg); JScrollPane editpanel = new JScrollPane(input); this.add(spanel); this.add(editpanel); this.add(msgSend); } /** * @param args */ public static void main(String[] args) throws IOException { // TODO Auto-generated method stub new TKClient(); } public void initSocket() { try { client = new Socket(this.host, this.port); writer = new OutputStreamWriter(client.getOutputStream()); // 建立连接后就可以往服务端写数据了 thread = new mythread(client, this); thread.start(); this.appendMsg("已连上服务器"); } catch (UnknownHostException e) { // TODO Auto-generated catch block e.printStackTrace(); this.appendMsg("不能连接上服务器"); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); this.appendMsg("不能连接上服务器"); } } public void appendMsg(String msg) { this.msg.append(msg + " "); } @Override public void actionPerformed(ActionEvent e) { // TODO Auto-generated method stub String temp = ""; try { if ("sendMsg".equals(e.getActionCommand())) { if ((temp = this.input.getText()) != null) { writer.write(temp); writer.flush(); this.appendMsg("我(" + this.client.getLocalPort() + ")说——>" + temp); this.input.setText(""); } } } catch (IOException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } } } class mythread extends Thread { private Socket socket = null; private Reader reader = null; private int len = 0; char chars[] = new char[64]; private TKClient client = null; private String temp = ""; public mythread(Socket socket, TKClient client) { // TODO Auto-generated constructor stub this.socket = socket; this.client = client; try { reader = new InputStreamReader(socket.getInputStream()); } catch (Exception e) { // TODO: handle exception } } @Override public void run() { // TODO Auto-generated method stub super.run(); System.out.println("客户端 子线程" + this.getId() + "-->开始工作"); while (true) { try { if (socket.isClosed() == false) { if (socket.isInputShutdown() == false) { while ((len = ((Reader) reader).read(chars)) != -1) { temp = "服务器说——>" + new String(chars, 0, len); client.appendMsg(temp); System.out.println(); } } } else { if (socket.getKeepAlive() == false) { reader.close(); socket.close(); this.stop(); } } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }