C/S(socket、執行緒 實現多個客戶端、伺服器端簡易通訊)

大川裡的小川人發表於2018-04-08
(要不要考慮點個贊!)

(第一篇部落格,滿懷激動寫下來的,可能調理不清楚,望理解)
首先是大概的結構框架:

一、客戶端詳解

客戶端的socket需要ip號:127.0.0.1,埠號:選大點1234。
實現通訊需要兩個方法:一個是寫入操作、一個是讀出操作。在例項化socket後,利用socket的inputStream和outputStream方法實現兩種操作。注意inputStream的方法需要封裝inputStreamReader到BufferedReader(其他也行)裡面。
下面附上原始碼:(因其中有一些加了雙斜線的程式碼可以忽略,是我在測試的時候用來看情況的,註釋沒有問題)

ChatClient.java:
package client;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;

public class ChatClient {
	
	public BufferedWriter  outTo;
	public String IP;
	public ChatClient(String ip) {
		this.IP = ip;
		// TODO Auto-generated constructor stub
		
	}
	

	Socket client;
	public void connect() {
//		String IP = "192.168.1.124";
		new Thread() {
			@Override
			public void run() {	
				try {
					client = new Socket(IP,1234);
					System.out.println("遠端主機地址:"+client.getRemoteSocketAddress());
				

					//輸出伺服器端的內容
					BufferedReader br = new BufferedReader(
							new InputStreamReader(client.getInputStream(),"UTF-8"));
					String line = null;
					while((line = br.readLine())!=null) {
						
						System.out.println(line);
						
					}
					
					String outString = "{'age':22,'sex':'男','userName':'xiapi'}";
					send(outString);
					
					br.close();


				} catch (UnknownHostException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}.start();
	}
	
	public void send(String outString) throws IOException {
		client.getOutputStream()
		.write((outString+"\n").getBytes("UTF-8"));
		
	}
	

}


_______________________________________________________________________

Chat_Test.java


package client;

import java.io.IOException;
import java.util.Scanner;

public class Chat_Test {

	public Chat_Test() {
		// TODO Auto-generated constructor stub
	}

	public static void main(String[] args) throws IOException {
		// TODO Auto-generated method stub

		String IP = "127.0.0.1";
		ChatClient chatdemo = new ChatClient(IP);
		chatdemo.connect();
		
		String str = null;
		Scanner in = new Scanner(System.in);
		while (true) {
			try {
				str = in.nextLine();
				
				chatdemo.send(str);
				
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
//		String s = "{'age':22,'sex':'男','userName':'xiapi'}";
//		chatdemo.send(s);
	}

}

二、伺服器端詳解:

伺服器端需要一個測試類、一個執行緒管理類、一個執行緒監聽類、一個執行緒類

伺服器端需要例項化serversocket,需要相同的埠。需要相同的inputStream、outpStream。不過相對於客戶端的out、伺服器是相應的input。
程式碼中使用了執行緒。ChatManager.Java是管理所有的連線執行緒的。並將所有的資訊傳送到其他連線了的客戶端。(eclipse中多開幾個控制檯可以測試)。chatSocket中,迴圈監聽所有的請求,請求成功就新增到執行緒管理類中。並時刻進行執行緒的資訊傳輸。


附上原始碼:

ChatManager.java

package socket;

import java.util.Vector;

/*
 * 要實現每個客戶端之間的通訊,則需要定義一個ChatManager來進行管理
 * */
public class ChatManager {

	private ChatManager() {
		// TODO Auto-generated constructor stub
	}
	private static final ChatManager cm = new ChatManager();
	
	public static ChatManager getChatManager() {
		return cm;
	}
	
	Vector<ChatSocket> vector = new Vector<ChatSocket>();
	
	
	public void add(ChatSocket cs) {
		vector.add(cs);//將每一個執行緒加入集合中
		
	}
	
	public void remove(ChatSocket cs) {
		vector.remove(cs);
	}
	
	public void giveToAll(ChatSocket cs , String chatinfo){
		//要給集合中所有的執行緒傳送資訊就必須遍歷這個集合
		for(int i=0; i<vector.size();i++) {
			ChatSocket csChatSocket = vector.get(i);

			if(!csChatSocket.equals(cs)) {
				csChatSocket.out(chatinfo);
			}
		}
	}


}


—————————————————————————————————————

ChatSocket.java

package socket;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.Socket;

public class ChatSocket extends Thread {

	Socket socket;
	public ChatSocket(Socket s) {
		this.socket = s;
		// TODO Auto-generated constructor stub
	}
	
	//返回給客戶端的一條已經連線到伺服器的資訊  to client
	public void out(String out) {
		try {
			socket.getOutputStream().write((out+"\n").getBytes("UTF-8"));
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			System.out.println("已經斷開了一個客服端連線"); 
			e.printStackTrace();
		}
	}
	
	@Override
	public void run() {
		out("已經連線");// to client
		try {
			//from   client
			BufferedReader br = new BufferedReader(
					new InputStreamReader(socket.getInputStream(),"UTF-8"));
			
			String line = null;
			
			while((line = br.readLine())!=null) {
				// 然後伺服器再將所有的資訊轉發給每一個客戶端,呼叫publish方法
				ChatManager.
				getChatManager().giveToAll(this, line);
				System.out.println(line);
			}
			br.close();
//			System.out.println("斷開了一個客戶端連結");
//			ChatManager.getChatManager().remove(this);

		} catch (UnsupportedEncodingException e) {


			e.printStackTrace();
		} catch (IOException e) {
			System.out.println("斷開了一個客戶端連結");
			ChatManager.getChatManager().remove(this);



			e.printStackTrace();
		}
		
		
		
	}


}


————————————————————————————————————————

ServerListener.java

package socket;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;



public class ServerListener extends Thread{

	public ServerListener() {
		// TODO Auto-generated constructor stub
	}

	@Override
	public void run() {
		try {
			ServerSocket serverSocket = new ServerSocket(1234);
			while(true) {
				Socket socket = serverSocket.accept();
				
				ChatSocket cs = new ChatSocket(socket);
				cs.start();
				ChatManager.getChatManager().add(cs);
			}
			
		}catch(IOException e) {
			e.printStackTrace();
		}
	}

}


————————————————————————————————————

ChatServer_Test.java

package test;

import socket.ServerListener;

public class ChatServer_Test {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		new ServerListener().start();
	}

}
(轉載請註明出處,謝謝!!!)

相關文章