实时群聊小程序开发记录
昨天回忆了一下以前做的一个实时的群聊小程序。用JAVA写得。开发步骤如下:
这是面向过程的开发。
第一步,建立服务器端。
第二步,建立客户端并连接服务端。
第三步,客户端发送消息服务器端能接收到。
第四步,实现多客户连接服务端,并能接收多客户端发来的消息。可以采用多线程和异步的方法解决服务端被占用的情况。
第五步,服务端转发客户端发送的信息到每一个客户端。
第六步,消除小Bug。
ChatServer.java
import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.EOFException; import java.util.*; import java.io.IOException; import java.net.BindException; import java.net.ServerSocket; import java.net.Socket; import java.net.SocketException; public class ChatServer { boolean started = false; ServerSocket ss = null; List<Client> clients = new ArrayList<Client>(); public static void main(String[] args) { new ChatServer().start(); } public void start(){ try { ss = new ServerSocket(8881); } catch (BindException e){ System.out.println("端口已被占用!"); System.out.println("请结束相关进程!"); System.exit(0); } catch (Exception e) { e.printStackTrace(); } try{ started = true; while (started) { Socket s = ss.accept(); //阻塞性函数,不断接收客户端连接 Client c = new Client(s);//不能再静态main()里面new一个动态的方法,故将启动过程包装成一个public函数 System.out.println("a client connected"); new Thread(c).start(); clients.add(c); } } catch (Exception e) { e.printStackTrace(); }finally{ try { ss.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } class Client implements Runnable{//区分客户端,用一个线程操作一个客户端,也可以采用异步的方法。这里用线程,比较占资源。等我写出异步的方法后再共享。 private Socket s= null; private DataInputStream dis= null; private DataOutputStream dos=null; private boolean bConnected = false; public Client(Socket s){ this.s= s; try { dis=new DataInputStream(s.getInputStream()); dos=new DataOutputStream(s.getOutputStream()); bConnected = true; } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public void send(String str){ // try { dos.writeUTF(str); } catch (IOException e) { // TODO Auto-generated catch block clients.remove(this); System.out.println("一个客户退出了!List已去除"); //e.printStackTrace(); } } public void run() { try { while (bConnected) { String str; str = dis.readUTF();// 阻塞性函数,会一直占用线程资源 System.out.println(str); for (int i = 0; i < clients.size(); i++) { Client c = clients.get(i); c.send(str); } } } catch (EOFException e){ System.out.println("一个客户已退出!"); }catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); }finally{ if(dis!=null) try { dis.close(); if (dos != null) dos.close(); if (s != null) s.close(); } catch (SocketException e) { clients.remove(this); System.out.println("一个客户已退出!"); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } }
ChatClient.java
import java.awt.BorderLayout; import java.awt.Frame; import java.awt.TextArea; 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.io.DataInputStream; import java.io.DataOutputStream; import java.io.EOFException; import java.io.IOException; import java.net.Socket; import java.net.SocketException; import java.net.UnknownHostException; public class ChatClient extends Frame { Socket s = null; DataOutputStream dos = null; DataInputStream dis = null; private boolean bConnected=false; TextField tfTxt = new TextField();//输入框 TextArea taContent = new TextArea();//显示聊天信息框 public static void main(String[] args) { new ChatClient().lanunchFrame(); } public void lanunchFrame(){ setLocation(400,300); this.setSize(300, 300); add(tfTxt,BorderLayout.SOUTH); add(taContent,BorderLayout.NORTH); pack();//调整空隙 this.addWindowListener(new WindowAdapter(){ @Override public void windowClosing(WindowEvent e) { disconnect(); System.exit(0); } }); tfTxt.addActionListener(new TexFileListener()); setVisible(true); connect(); new Thread(new RecvThread()).start(); } public void connect(){ try { s= new Socket("127.0.0.1",8881); dos=new DataOutputStream(s.getOutputStream()); dis=new DataInputStream(s.getInputStream()); System.out.println("connected!"); bConnected =true; } catch (UnknownHostException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } public void disconnect() { try { dos.close(); dis.close(); s.close(); } catch (Exception e1) { e1.printStackTrace(); } /*try { bConnected = false; //保证 recvThread.join(); } catch (InterruptedException e){ e.printStackTrace(); } finally{ try { dos.close(); dis.close(); s.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } */ } private class TexFileListener implements ActionListener{ public void actionPerformed(ActionEvent e) { String str=tfTxt.getText().trim(); //taContent.setText(str); tfTxt.setText(""); try { dos.writeUTF(str); dos.flush(); //dos.close(); } catch (IOException e1) { e1.printStackTrace(); } } } private class RecvThread implements Runnable{ public void run() { try { while (bConnected) { String str = dis.readUTF(); //System.out.println(str); taContent.setText(taContent.getText()+str+'\n'); } } catch (SocketException e){ System.out.println("已退出!"); } catch (EOFException e){ System.out.println("已退出!"); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }
更多实时群聊小程序开发记录 相关文章请关注PHP中文网!

Alat AI Hot

Undresser.AI Undress
Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover
Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool
Gambar buka pakaian secara percuma

Clothoff.io
Penyingkiran pakaian AI

AI Hentai Generator
Menjana ai hentai secara percuma.

Artikel Panas

Alat panas

Notepad++7.3.1
Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina
Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1
Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6
Alat pembangunan web visual

SublimeText3 versi Mac
Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Topik panas



Pengendalian pengecualian fungsi dalam C++ amat penting untuk persekitaran berbilang benang untuk memastikan keselamatan benang dan integriti data. Pernyataan cuba-tangkap membolehkan anda menangkap dan mengendalikan jenis pengecualian tertentu apabila ia berlaku untuk mengelakkan ranap program atau rasuah data.

PHP multithreading merujuk kepada menjalankan berbilang tugas secara serentak dalam satu proses, yang dicapai dengan mencipta benang berjalan secara bebas. Anda boleh menggunakan sambungan Pthreads dalam PHP untuk mensimulasikan tingkah laku berbilang benang Selepas pemasangan, anda boleh menggunakan kelas Thread untuk mencipta dan memulakan utas. Contohnya, apabila memproses sejumlah besar data, data boleh dibahagikan kepada berbilang blok dan bilangan benang yang sepadan boleh dibuat untuk memprosesnya secara serentak untuk meningkatkan kecekapan.

Terdapat dua pendekatan biasa apabila menggunakan JUnit dalam persekitaran berbilang benang: ujian berbenang tunggal dan ujian berbilang benang. Ujian berutas tunggal dijalankan pada utas utama untuk mengelakkan isu konkurensi, manakala ujian berbilang utas dijalankan pada utas pekerja dan memerlukan pendekatan ujian disegerakkan untuk memastikan sumber yang dikongsi tidak terganggu. Kes penggunaan biasa termasuk menguji kaedah selamat berbilang benang, seperti menggunakan ConcurrentHashMap untuk menyimpan pasangan nilai kunci, dan utas serentak untuk beroperasi pada pasangan nilai kunci dan mengesahkan ketepatannya, mencerminkan aplikasi JUnit dalam persekitaran berbilang benang. .

Teknik concurrency dan multithreading menggunakan fungsi Java boleh meningkatkan prestasi aplikasi, termasuk langkah berikut: Memahami konsep concurrency dan multithreading. Manfaatkan pustaka konkurensi dan berbilang benang Java seperti ExecutorService dan Callable. Amalkan kes seperti pendaraban matriks berbilang benang untuk memendekkan masa pelaksanaan. Nikmati kelebihan peningkatan kelajuan tindak balas aplikasi dan kecekapan pemprosesan yang dioptimumkan yang dibawa oleh concurrency dan multi-threading.

Dalam persekitaran berbilang benang, gelagat fungsi PHP bergantung pada jenisnya: Fungsi biasa: thread-safe, boleh dilaksanakan secara serentak. Fungsi yang mengubah suai pembolehubah global: tidak selamat, perlu menggunakan mekanisme penyegerakan. Fungsi operasi fail: tidak selamat, perlu menggunakan mekanisme penyegerakan untuk menyelaraskan akses. Fungsi operasi pangkalan data: Mekanisme sistem pangkalan data yang tidak selamat perlu digunakan untuk mengelakkan konflik.

Mutex digunakan dalam C++ untuk mengendalikan sumber perkongsian berbilang benang: buat mutex melalui std::mutex. Gunakan mtx.lock() untuk mendapatkan mutex dan menyediakan akses eksklusif kepada sumber yang dikongsi. Gunakan mtx.unlock() untuk melepaskan mutex.

Pengujian program berbilang benang menghadapi cabaran seperti ketidakbolehulangan, ralat konkurensi, kebuntuan dan kekurangan keterlihatan. Strategi termasuk: Ujian unit: Tulis ujian unit untuk setiap utas untuk mengesahkan kelakuan utas. Simulasi berbilang benang: Gunakan rangka kerja simulasi untuk menguji program anda dengan kawalan ke atas penjadualan benang. Pengesanan perlumbaan data: Gunakan alat untuk mencari perlumbaan data yang berpotensi, seperti valgrind. Nyahpepijat: Gunakan penyahpepijat (seperti gdb) untuk memeriksa status program masa jalan dan mencari sumber perlumbaan data.

Dalam persekitaran berbilang benang, pengurusan memori C++ menghadapi cabaran berikut: perlumbaan data, kebuntuan dan kebocoran memori. Tindakan balas termasuk: 1. Menggunakan mekanisme penyegerakan, seperti mutex dan pembolehubah atom 2. Menggunakan struktur data tanpa kunci 3. Menggunakan penunjuk pintar 4. (Pilihan) Melaksanakan pengumpulan sampah;
