學習計算機網絡編程也有一段時間了,對這段時間學習的東西做一個小總結吧,主要是基於socket,實現客戶端和服務器的通信,編程用java語言。具體的實驗要求如下:
設計程序,分別構建通信的兩端:服務器端和客戶端應用程序,套接字類型爲面向連接的Socket,自己構建雙方的應答模式,實現雙方的數據的發送和接收(S發給C,C發給S)。
服務端程序能響應單個或任意多個客戶端連接請求;服務端能向單個客戶發送消息,支持羣發消息給所有客戶端;
通信的雙方具備異常響應功能,包括對方異常退出的處理。如果客戶端退出,服務器有響應;反之亦然。
Client-Server通信效果的圖片說明:
編程實現的思路:在服務器端,首先要啓動一條線程用於監聽某個指定端口(比如:8000),並且還要再開一條線程用於接收消息,客戶端嘗試連接該端口(8000),如果成功連接則會返回一個Socket類的實例對象(Socket socket = serversocket.accept();) ,很顯然服務器端便應該保存有一個客戶列表(比如可以用:ArrayList),使得服務器可以發消息給某個指定的客戶端。而客戶端在連接服務器之後也應該啓動一條線程用於接收消息。當某個客戶端進來時,便發送Login消息給服務器,服務器將此消息廣播發給當前在線的所有用戶,當某個客戶端退出時,發送Logout消息給服務器,服務器將此消息廣播發給當前在線的所有用戶,當客戶端之間進行通信時,會發送Talk消息給服務器,服務器再將此消息轉發給指定的客戶端,也就是所有的通信都是通過服務器進行轉發的。
主要的代碼實現如下:
服務器端:
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.ArrayList;
import javax.swing.JScrollBar;
public class ChatServer extends javax.swing.JFrame {
ArrayList<User> list = new ArrayList<User>();
static String local;
int port = 8000;
boolean isNomalexit = false;
Mythread jtThread;
public ChatServer() {
initComponents();
this.setTitle("服務器");
this.setResizable(false);
this.setLocationRelativeTo(null);
this.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
super.windowClosing(e);
dispose();
}
});
}
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) { } //開始監聽按鈕的事件
private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) { } //停止監聽按鈕的事件
class Mythread extends Thread{ } //負責監聽端口8000的線程
class ClientThread extends Thread{ } //負責接收消息的線程
public void sendtoclient(User user,String message){ } //發送消息message給用戶,user爲發送者
public void sendtoallclient(User user,String message){ } //發送消息message給所有用戶,user發送者
public void removeuser(User user){ }
public static void main(String args[]) throws UnknownHostException {
local = InetAddress.getLocalHost().getHostAddress();
ChatServer frame = new ChatServer();
frame.setVisible(true);
}
客戶端:
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.net.InetAddress;
import java.net.Socket;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JOptionPane;
import javax.swing.JScrollBar;
public class ChatClient extends javax.swing.JFrame {
Socket s;
boolean isExit = false;
DataInputStream in;
PrintStream out;
ArrayList<String> list =new ArrayList<String>();
static String name;
ReceivemessageThread thread;
public ChatClient() {
initComponents();
this.setTitle("客戶端");
this.setResizable(false);
this.setLocationRelativeTo(null);
this.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
if(s!=null){
sendmessage("Logout " + name);
try {
isExit = true;
in.close();
out.close();
s.close();
} catch (IOException ex) {
Logger.getLogger(ChatClient.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
});
}
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt){ } //登錄按鈕的事件
private void jButton2ActionPerformed(java.awt.event.ActionEvent evt){ } //發送按鈕的事件
class ReceivemessageThread extends Thread{ } // 接收消息的線程
public void sendmessage(String message){ } //發送消息
public void removeuser(String name){ } //移除在線列表上的用戶名
public static void main(String args[]) {
ChatClient frame = new ChatClient();
frame.setVisible(true);
}
運行演示:
在做完這個程序之後,對於網絡編程也算是基本上入門了,後續還會有很多的通信程序,因爲這門課的要求就是做一個類似QQ的通信程序,寫下這篇博客也算是記錄自己的學習進程。