通过TCP网络协议实现控制台多人聊天功能,另附私聊@功能。(java)
通過TCP網(wǎng)絡(luò)協(xié)議實現(xiàn)控制臺多人聊天功能,另附私聊@功能。(java)
何為TCP?我們應(yīng)該首先知道這一個概念,TCP是一種可靠的、基于連接的網(wǎng)絡(luò)協(xié)議,它是面向字節(jié)流的,即從一個經(jīng)常到另一個進程的二進制序列。每一條TCP連接需要兩個端點,一個是接受消息的端口,我們通常叫它為服務(wù)端,和發(fā)送消息的端口,我們通常叫它為客戶端。
客戶端實現(xiàn)細聊
每一個用戶在啟動的時候就用了一個Socket,因為要實現(xiàn)多人聊天所以就需要給每一個用戶添加一個用戶線程,防止在實現(xiàn)過程中出現(xiàn)阻塞的問題。
用戶線程實現(xiàn)Runable接口,在run()方法里面不斷讀取從服務(wù)端傳來的消息,其代碼如下所示:
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.Socket;public class ClientThread implements Runnable{private Socket s;BufferedReader br = null;public ClientThread(Socket s) throws IOException {this.s = s;br = new BufferedReader(new InputStreamReader(s.getInputStream()));}@Overridepublic void run() {try{String content = null;while ((content = br.readLine()) != null){System.out.println(content);}} catch (IOException e) {e.printStackTrace();}} }另外我在這里實現(xiàn)了3個客戶,每一個客戶都開啟一個多線程,由于每個用戶實現(xiàn)的代碼相同,所以只貼出一份。
 代碼如下:
服務(wù)端實現(xiàn)細聊
首先我們需要定義一個User類,其作用就是給每一個客戶(Socket)給定一個唯一標識姓名。代碼如下:
import java.net.Socket;public class User {private Socket socket;private String name;public User() {}public User(Socket socket, String name) {this.socket = socket;this.name = name;}public Socket getSocket() {return socket;}public void setSocket(Socket socket) {this.socket = socket;}public String getName() {return name;}public void setName(String name) {this.name = name;}@Overridepublic String toString() {return "User{" +"socket=" + socket +", name='" + name + '\'' +'}';} }當(dāng)服務(wù)器開啟后,就會等待客戶上線,然后連接客戶,此時服務(wù)端就接收到了這一個用戶,然后我們將這個客戶(Socket)添加到User用戶類,由于此時客戶只是上線了,還未輸入姓名,所以此時的每一個客戶姓名都為null,當(dāng)我們輸入姓名的時候,再返回看看客戶代碼我們給用戶的姓名做了一點小小的操作,就是添加了兩個!!,所以!xxx!,這兩個!里面的就是姓名,而我們就需要去判斷是否為!開頭以及結(jié)尾,若是就判斷他是這個客戶的姓名,然后我們再為每一個用戶設(shè)置一個姓名。
 代碼如下:
然后我們需要定義一個currentUser來確定從當(dāng)前控制臺輸入的這個用戶是誰,原理是通過從端口號是否相等來判斷出是否為是這一個currentUser。代碼如下所示:
//獲取當(dāng)前用戶傳來的消息 if (!flag_name && flag_port){currentUser = user;message = user.getName() + ": " + content;System.out.println(message); //得到客戶端傳來的話 }就這樣我們就確定了當(dāng)前輸入消息的人是誰了,然后就可以不把該用戶說的話傳給自己啦。實現(xiàn)方法為遍歷該系統(tǒng)中所有的用戶,如果是currentUser就跳過,代碼如下所示:
for (User user : users) {if (!user.equals(currentUser)) {PrintStream ps = new PrintStream(user.getSocket().getOutputStream());ps.println(message);} }通過以上的代碼就已經(jīng)實現(xiàn)了多人聊天功能了,然后我們在實現(xiàn)私聊@功能吧。
私聊往往都是通過@來實現(xiàn)的,但是@+姓名這才是真正的私聊某人,但是還有一種情況那就是如果@+錯誤的名字,那么這也會發(fā)生錯誤。所以我們也要排出這種情況。
 當(dāng)我們確定了是否為私聊后我們才能去實現(xiàn)發(fā)送私聊消息這些操作。我們再來分析一波這個私聊功能,當(dāng)一個用戶@了某一個人XXX后發(fā)送的這句消息我們只能發(fā)送給被@的這個人XXX,然后再XXX用戶可以看到是誰向他說話了,分析完畢,讓我們來看看代碼吧,代碼如下所示:
服務(wù)器的具體功能已經(jīng)實現(xiàn)了,若還未懂的話可以再看看下面的具體代碼,如下所示:
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintStream; import java.net.Socket; import java.util.ArrayList;public class ServerThread implements Runnable{Socket s = null;String message = null;BufferedReader br = null;public ServerThread() {}public ServerThread(Socket s) throws IOException {this.s = s;br = new BufferedReader(new InputStreamReader(s.getInputStream()));}@Overridepublic void run() {try{String content = null;while((content = readFormClient()) != null){ArrayList<User> users = Server.socketList;User currentUser = null; //當(dāng)前用戶boolean flag_name = false;boolean flag_port = false;for (User user : Server.socketList) {//判斷是否為用戶姓名,如果是就設(shè)置這個用戶的姓名flag_name = content.startsWith("!") && content.endsWith("!");flag_port = this.s.getPort() == user.getSocket().getPort();if (flag_name && flag_port){//分割出用戶姓名user.setName(content.substring(1, content.length() - 1));}//獲取當(dāng)前用戶傳來的消息if (!flag_name && flag_port){currentUser = user;message = user.getName() + ": " + content;System.out.println(message); //得到客戶端傳來的話}}String privateMessage = null; //私聊消息String privateName = null; //私聊用戶名User privateUser = null; //私聊用戶boolean flag_private = false;if (message != null){//如果有@符號說明就私聊if (message.contains(": @")){for (User value : users) {String username = value.getName();//私聊某人if (message.contains(": @" + username)) {privateName = username;//提取出私聊某人的內(nèi)容privateMessage = message.split("@" + username)[1];flag_private = true;}}// 通過私聊用戶名獲取該用戶for (User user : users) {if (user.getName().equals(privateName)) {privateUser = user;}}if (flag_private){assert privateUser != null;PrintStream ps = new PrintStream(privateUser.getSocket().getOutputStream());ps.println(message.split(":")[0] + ": "+ privateMessage);}else {assert currentUser != null;PrintStream ps = new PrintStream(currentUser.getSocket().getOutputStream());ps.println("沒有找到這個人嘞!!!");}}else {//傳入當(dāng)前用戶給其他用戶輸入的消息for (User user : users) {if (!user.equals(currentUser)) {PrintStream ps = new PrintStream(user.getSocket().getOutputStream());ps.println(message);}}}}}} catch (IOException e) {e.printStackTrace();}}/*** 讀取用戶發(fā)來的每一條消息* @return*/private String readFormClient(){try{return br.readLine();}catch (IOException e){Server.socketList.remove(s);}return null;} }最后我們則需要在服務(wù)器里面一直開啟上面這個服務(wù)器線程,另外還要定義一個ArrayList集合來裝入上線的用戶。代碼如下所示:
import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; import java.util.ArrayList;public class Server {//存儲所有的客戶public static ArrayList<User> socketList = new ArrayList<>();public static void main(String[] args) throws IOException {ServerSocket ss = new ServerSocket(3000);while (true){Socket s = ss.accept();User user = new User(s, "");socketList.add(user);//為每一個客戶添加一個服務(wù)端多線程new Thread(new ServerThread(s)).start();}} }就這樣我們實現(xiàn)的通過TCP網(wǎng)絡(luò)協(xié)議實現(xiàn)控制臺多人聊天功能,另附私聊@功能就這樣完成咯。
 最后我們看一看實現(xiàn)的效果吧,首先我們先將服務(wù)器開著,等待用戶連接,當(dāng)用戶連接了就給自己輸入一個姓名,我在這里開啟了三個用戶。
 
 
 
總結(jié)
以上是生活随笔為你收集整理的通过TCP网络协议实现控制台多人聊天功能,另附私聊@功能。(java)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
                            
                        - 上一篇: 易到用车服务器修复了提现,易到用车提现最
 - 下一篇: S32K144_FTM定时器中断