天天看點

Java Socket和ServerSocket通信伺服器 聊天功能 的實作

在客戶/伺服器通信模式中,伺服器端需要建立監聽特定端口的ServerSocket,ServerSocket負責接收客戶連接配接請求。首先介紹ServerSocket類的各個構造方法,以及成員方法的用法,接着介紹伺服器如何用多線程來處理與多個客戶的通信任務。

ServerSocket的構造方法有以下幾種重載形式:

◆ServerSocket()throws IOException 
◆ServerSocket(int port) throws IOException 
◆ServerSocket(int port, int backlog) throws IOException
◆ServerSocket(int port, int backlog, InetAddress bindAddr) throws IOException
           

在以上構造方法中,參數port指定伺服器要綁定的端口(伺服器要監聽的端口),參數backlog指定客戶連接配接請求隊列的長度,參數bindAddr指定伺服器要綁定的IP位址。

除了第一個不帶參數的構造方法以外,其他構造方法都會使伺服器與特定端口綁定,該端口由參數port指定。例如,以下代碼建立了一個與9999端口綁定的伺服器:

ServerSocket serverSocket=new ServerSocket(9999);
           

如果運作時無法綁定到80端口,以上代碼會抛出IOException,更确切地說,是抛出BindException,它是IOException的子類。BindException一般是由以下原因造成的:

◆端口已經被其他伺服器程序占用;

◆在某些作業系統中,如果沒有以超級使用者的身份來運作伺服器程式,那麼作業系統不允許伺服器綁定到1~1023之間的端口。0~1023之間的端口是用于綁定Binding的一些服務的端口。

如果把參數port設為0,表示由作業系統來為伺服器配置設定一個任意可用的端口。由作業系統配置設定的端口也稱為匿名端口。對于多數伺服器,會使用明确的端口,而不會使用匿名端口,因為客戶程式需要事先知道伺服器的端口,才能友善地通路伺服器。

聊天伺服器小Demo

/**
 * ServerSocket簡單聊天伺服器
 * @author 鐘宇峰
 */
public class ServerDemo  {
	private Socket socket;
	private ServerSocket server;
	//主函數
	public static void main(String[] args) {
		ServerDemo sd = new ServerDemo();
		sd.createServer(9999);
	}
	/**
	 * 建立伺服器
	 * @param port 端口号
	 */
	public void createServer(int port){
		try {
			//建立伺服器
			 server = new ServerSocket(port);
			System.out.println("伺服器建立成功....");
			System.out.println("伺服器處于阻塞狀态中,等待客戶機連接配接.....");
			//伺服器阻塞中等待客戶機連接配接
			whlie(true){
				socket = server.accept();
				System.out.println("客戶機"+(i-1)+"連接配接成功!"+socket.getRemoteSocketAddress());
				ClientDemo cd = new ClientDemo(server,socket);
				cd.start();
			}
			//客戶機已連接配接
			server.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}
-----------------------------------------------------------------------------
public class ClientDemo extends Thread {
	private ServerSocket server;
	private Socket socket;

	public ClientDemo(ServerSocket server, Socket socket) {
		this.socket = socket;
		this.server = server;
	}

	public void run() {
		while (true) {
			try {
				OutputStream os = socket.getOutputStream();
				// BufferedReader br = new BufferedReader(new
				// InputStreamReader(is));
				InputStream is = socket.getInputStream();
				String msg = "歡迎登陸聊天室!\r\n";
				os.write(msg.getBytes());

				msg = "";
				while (!msg.equals("exit")) {
					int i = 0;
					StringBuffer strb = new StringBuffer();
					while ((i = is.read()) != 13) {//
						// 讀取客戶機發送過來的消息,隻要不是13就繼續讀取,如果是13則結束
						strb.append((char) i);
					}
					is.read();// 讀取換行符,丢掉
					msg = strb.toString();
					// msg = br.readLine();
					System.out.println("客戶機說:" + msg);
					os.write(("伺服器說:" + msg + "\r\n").getBytes());
				}
				os.close();
				socket.close();

			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
}

      
           

在伺服器建立中我們使用while(true){}循環確定伺服器不會停止,一直處于阻塞狀态中等待連接配接進來的客戶機。ClientDemo類繼承了線程,在run方法中建立客戶機對象,初始化IO流。這樣我們就可以生成多個用戶端進而實作聊天功能。在這個基礎上可以逐漸加深,實作群聊功能,私聊,寫自己設計的界面,制定通信協定以實作諸多功能。

繼續閱讀