以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("服務器消息接收器\r\n\n"); 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 + "\r\n"); } 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("客戶端消息接收器\r\n\n"); 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 + "\r\n"); } @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(); } } } }