자바 다 중 스 레 드 채 팅 실현
다 중 스 레 드 로 이 루어 지면 기능 이 단일 스 레 드 채 팅 방 보다 더욱 완비 되 고 인성 화 될 것 이다.
다 중 스 레 드 버 전의 채 팅 방
1.기능 분석:
사용자 등록,온라인,오프라인 실현단체 채 팅 과 개인 채 팅 실현현재 온라인 인원수 통계
2.서버 구현
1.모든 온라인 사용자 유지
2.등록 기능:클 라 이언 트 이름,서버 의 클 라 이언 트 집합 에 추가
3.단체 채 팅 기능:클 라 이언 트 가 메 시 지 를 보 내 면 모든 클 라 이언 트 가 받 을 수 있 습 니 다.
4.개인 채 팅 기능:클 라 이언 트 와 지 정 된 클 라 이언 트 가 메 시 지 를 보 내 고 받 습 니 다.
5.종료 기능:서버 클 라 이언 트 집합 에서 클 라 이언 트 제거
3.클 라 이언 트 실현
1.등록 기능:Socket 대상 을 만 들 고 서버 에 등록 실행(메시지)을 보 냅 니 다.
2.단체 채 팅 기능:클 라 이언 트 전송 및 수신 데이터
3.개인 채 팅 기능:클 라 이언 트 가 클 라 이언 트(사용자)를 지정 하고 데 이 터 를 보 내 고 받 습 니 다.
4.종료 기능:서버 에 종료 명령(메시지)보 내기
5.명령 행 의 대화 식 입 출력
4.사고의 실현:
우선,서버 와 클 라 이언 트 간 의 연결 을 실현 해 야 한다.
소켓 을 사용 하여 TCP 연결 을 만 듭 니 다:
(1)서버 쪽 에서 서버 포트 번 호 를 설명 하 는 ServerSocket 대상 을 예화 합 니 다.
(2)클 라 이언 트 가 지정 한 서버 에 연결 하기 위해 Socket 대상 을 만 들 려 고 합 니 다.
(3)서버 에서 서버 에 연 결 된 클 라 이언 트 정 보 를 감청 하기 위해 ServerSocket 류 의 accept()방법 을 호출 합 니 다.
(4)서버 측 과 클 라 이언 트 의 연결 이 성공 하면 쌍방 은 Socket 대상 을 되 돌려 줍 니 다.이때 쌍방 은 통신 을 할 수 있 습 니 다.
(5)서버 쪽 과 클 라 이언 트 는 I/O 흐름 을 사용 하여 연결 하고 서버 의 출력 흐름 은 클 라 이언 트 의 입력 흐름 을 연결 하 며 클 라 이언 트 의 출력 흐름 은 서버 의 입력 흐름 을 연결 합 니 다.
(6)close()방법 으로 소켓 을 닫 습 니 다(닫 는 것 을 기억 하 세 요)
2.하나의 서버 를 가지 고 여러 클 라 이언 트 의 연결 을 실현 하기 때문에 여기 서 해결 해 야 할 것 은 다 중 스 레 드 문제 입 니 다.
각 클 라 이언 트 는 서버 에 메 시 지 를 보 내 고 서버 에 메 시 지 를 받 는 두 개의 스 레 드 가 필요 합 니 다.
한편,서버 는 클 라 이언 트 와 서버 의 연결 을 추가 할 때마다 서버 는 클 라 이언 트 와 의 연결 을 처리 하기 위해 스 레 드 를 하나 더 만들어 야 합 니 다.
5.그림 해석
6. 서버 코드 구현
서버 클래스
package test.Server;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* package:test.Server
* Description:
* @date:2019/8/14
* @Author:weiwei
**/
public class server {
public static void main(String[] args) {
try {
int port = 6666;
ServerSocket serverSocket = new ServerSocket(port);
System.out.println(" ..." + serverSocket.getLocalSocketAddress()); // ,
//
ExecutorService executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * 2);
while (true) { //
Socket client = serverSocket.accept();
System.out.println(" :" + client.getRemoteSocketAddress());
executorService.execute(new HandlerClient(client));
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
HandlerClient 클래스
package test.Server;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.util.Map;
import java.util.Scanner;
import java.util.concurrent.ConcurrentHashMap;
/**
* Author:weiwei
* description:HandlerClient
* Creat:2019/3/12
**/
public class HandlerClient implements Runnable {
/**
*
*/
private static final Map<String,Socket> ONLINE_CLIENT_MAP =
new ConcurrentHashMap<String, Socket>(); // ,final ,ConcurrentHashMap
//static final --
private final Socket client;
public HandlerClient(Socket client) { //HandlerClient , , HashMap
this.client = client; // , final
}
//@Override
public void run() {
try {
InputStream clientInput=client.getInputStream(); //
Scanner scanner = new Scanner(clientInput); //
/**
*
* 1.register:<username> : register:
* 2. : groupChat:<message> :groupChat:
* 3. : privateChat: : ,
* 4. :bye
*/
while(true){
String data = scanner.nextLine(); // ,
if(data.startsWith("register:")){
//
String userName = data.split(":")[1];// ,
register(userName);
continue;
}
if(data.startsWith("groupChat:")){
String message = data.split(":")[1];
groupChat(message);
continue;
}
if(data.startsWith("privateChat:")){
String [] segments = data.split(":");
String targetUserName = segments[1].split("\\-")[0]; //
String message = segments[1].split("\\-")[1]; // , //
privateChat(targetUserName,message);
continue;
}
if(data.equals("bye")){
//
bye();
continue;
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
/**
*
*/
private void bye() {
for(Map.Entry<String,Socket> entry : ONLINE_CLIENT_MAP.entrySet()){
Socket target = entry.getValue();
if(target.equals(this.client)){ //
ONLINE_CLIENT_MAP.remove(entry.getKey());
break;
}
System.out.println(getCurrentUserName()+" ");
}
printOnlineClient();//
}
private String getCurrentUserName(){
for (Map.Entry<String, Socket> entry : ONLINE_CLIENT_MAP.entrySet()) {
Socket target = entry.getValue(); //getvalue Socket
if(target.equals(this.client)){ //
return entry.getKey();
}
}
return "";
}
/**
* , targetUserName message
* @param targetUserName
* @param message
*/
private void privateChat(String targetUserName, String message) {
Socket target = ONLINE_CLIENT_MAP.get(targetUserName);//
if(target == null){
this.sendMessage(this.client," "+targetUserName,false);
}else{
this.sendMessage(target,message,true);
}
}
/**
* , message
* @param message
*/
private void groupChat(String message) {
for (Map.Entry<String, Socket> entery : ONLINE_CLIENT_MAP.entrySet()) {
Socket target = entery.getValue(); //getvalue Socket
if(target.equals(this.client)){
continue; //
}
this.sendMessage(target,message,true);
}
}
/**
* userName key (Socket client)
* @param userName
*/
private void register(String userName) {
if(ONLINE_CLIENT_MAP.containsKey(userName)){
this.sendMessage(this.client," , ",false);
}else{
ONLINE_CLIENT_MAP.put(userName,this.client);
printOnlineClient();
this.sendMessage(this.client," "+userName+"
",false);
}
}
private void sendMessage(Socket target,String message,boolean prefix){
OutputStream clientOutput = null; //value
try {
clientOutput = target.getOutputStream();
OutputStreamWriter writer = new OutputStreamWriter(clientOutput);
if(prefix) {
String currentUserName = this.getCurrentUserName();
writer.write("<" + currentUserName + " :>" + message + "
");
}else{
writer.write( message + "
");
}
writer.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
*
*/
private void printOnlineClient(){
System.out.println(" :"+ONLINE_CLIENT_MAP.size()+","+" :");
for(String userName : ONLINE_CLIENT_MAP.keySet()){ //Map key
System.out.println(userName);
}
}
}
7.클 라 이언 트 코드 구현 클 라 이언 트 클래스
package Cilent;
import java.io.IOException;
import java.net.Socket;
/**
* package:Cilent
* Description:
* @date:2019/8/14
* @Author:weiwei
**/
public class cilent {
public static void main(String[] args) {
try {
//
String host = "127.0.0.1";
//
int port = 6666;
Socket client = new Socket(host,port); // ,
new ReadDataFromServerThread(client).start();//
new WriteDataToServerThread(client).start();//
} catch (IOException e) {
e.printStackTrace();
}
}
}
WriteDateToServer 클래스
package Cilent;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.util.Scanner;
/**
* Author:weiwei
* description:
*
* Creat:2019/3/12
**/
public class WriteDataToServerThread extends Thread{
private final Socket client;
public WriteDataToServerThread(Socket client){
this.client = client;
}
@Override
public void run(){
try {
OutputStream clientOutput = this.client.getOutputStream();
OutputStreamWriter writer = new OutputStreamWriter(clientOutput);
Scanner scanner = new Scanner(System.in); //
while(true){
System.out.print(" >>");
String data = scanner.nextLine(); //
writer.write(data+"
");
writer.flush();
if(data.equals("bye")){
System.out.println(" ...");
break;
}
}
this.client.close();
} catch (IOException e) {
// e.printStackTrace();
}
}
}
ReadDateFromServer 클래스
package Cilent;
import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;
import java.util.Scanner;
/**
* Author:weiwei
* description:
* Creat:2019/3/12
**/
public class ReadDataFromServerThread extends Thread {
private final Socket client;
public ReadDataFromServerThread(Socket client){
this.client=client;
}
@Override
public void run(){
try {
InputStream clientInput = this.client.getInputStream();
Scanner scanner = new Scanner(clientInput);
while(true){
String data = scanner.nextLine();//
System.out.println(" :"+data);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Is Eclipse IDE dying?In 2014 the Eclipse IDE is the leading development environment for Java with a market share of approximately 65%. but ac...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.