java socket多執行緒實現聊天室
阿新 • • 發佈:2018-11-30
java socket多執行緒實現聊天室
程式碼放在我的GitHub上點選檢視
版本1,一對一,收發有順序
/**
* @Author: Hzw
* @Time: 2018/4/19 11:38
* @Description: 聊天室客戶端V1.0,雙向通訊,客戶端傳送後服務端才可以傳送,客戶端傳送前伺服器傳送的話,
* 訊息儲存在緩衝區中,等待客戶端傳送訊息後,緩衝區的訊息才會傳送
*/
public class ChatClient {
private Socket socket;
public ChatClient(){
try {
this.socket = new Socket("127.0.0.1", 8888);
} catch (IOException e) {
e.printStackTrace();
}
}
public void start(){
try{
OutputStream outputStream = socket.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter (outputStream);
PrintWriter pw = new PrintWriter(osw, true);
Scanner sc = new Scanner(System.in);
InputStream inputStream = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(inputStream);
BufferedReader br = new BufferedReader (isr);
while (true){
pw.println(sc.nextLine());
System.out.println(br.readLine());
}
}catch (Exception e){
e.printStackTrace();
}finally {
if (socket != null){
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args){
ChatClient client = new ChatClient();
client.start();
}
}
/**
* @Author: Hzw
* @Time: 2018/4/19 11:59
* @Description:
*/
public class ChatServer {
private ServerSocket serverSocket;
public ChatServer(){
try {
this.serverSocket = new ServerSocket(8888);
} catch (IOException e) {
e.printStackTrace();
}
}
public void start(){
try {
//接收客戶端傳送的訊息
Socket socket = serverSocket.accept();
InputStream inputStream = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(inputStream, "utf-8");
BufferedReader br = new BufferedReader(isr);
//傳送訊息給客戶端
OutputStream outputStream = socket.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(outputStream);
PrintWriter pw = new PrintWriter(outputStream, true);
Scanner scanner = new Scanner(System.in);
while (true){
System.out.println(br.readLine());
pw.println(scanner.nextLine());
}
}catch (Exception e){
e.printStackTrace();
}
}
public static void main(String[] args){
ChatServer chatServer = new ChatServer();
chatServer.start();
}
}
版本2,一對一,多執行緒,收發無順序
/**
* @Author: Hzw
* @Time: 2018/4/19 14:01
* @Description: 由於版本1客戶端和伺服器都有收發功能,並且收發有相應的順序,都對應相應的阻塞:緩衝區br.readLine(),
* 鍵盤輸入sc.nextLine(),版本2將改進,將收發分配給相應的執行緒處理,避免了阻塞
*/
@SuppressWarnings("all")
public class ChatClient {
private Socket socket;
public ChatClient(){
try {
socket = new Socket("127.0.0.1", 8888);
} catch (IOException e) {
e.printStackTrace();
}
}
public void start(){
Thread sendThread = new Thread(new SendThread());
Thread receiveThread = new Thread(new ReceiceThread());
sendThread.start();
receiveThread.start();
}
public static void main(String[] args){
ChatClient chatClient = new ChatClient();
chatClient.start();
}
public class SendThread implements Runnable{
@Override
public void run() {
try {
OutputStream outputStream = socket.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(outputStream);
PrintWriter pw = new PrintWriter(osw, true);
Scanner scanner = new Scanner(System.in);
while (true){
pw.println(scanner.nextLine());
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
public class ReceiceThread implements Runnable{
@Override
public void run() {
try {
InputStream inputStream = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(inputStream);
BufferedReader br = new BufferedReader(isr);
while (true){
System.out.println(br.readLine());
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* @Author: Hzw
* @Time: 2018/4/19 14:00
* @Description:
*/
@SuppressWarnings("all")
public class ChatServer {
private ServerSocket serverSocket;
private Socket socket;
public ChatServer(){
try {
serverSocket = new ServerSocket(8888);
socket = serverSocket.accept();
} catch (IOException e) {
e.printStackTrace();
}
}
public void start(){
Thread sendThread = new Thread(new SendThread());
Thread receiveThread = new Thread(new ReceiveThread());
sendThread.start();
receiveThread.start();
}
public static void main(String[] args){
ChatServer chatServer = new ChatServer();
chatServer.start();
}
public class SendThread implements Runnable{
@Override
public void run() {
try {
OutputStream outputStream = socket.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(outputStream);
PrintWriter pw = new PrintWriter(osw, true);
Scanner scanner = new Scanner(System.in);
while(true){
pw.println(scanner.nextLine());
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
public class ReceiveThread implements Runnable{
@Override
public void run() {
try {
InputStream inputStream = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(inputStream);
BufferedReader br = new BufferedReader(isr);
while (true){
System.out.println(br.readLine());
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
版本3,一對多,收發無順序,多執行緒
/**
* @Author: Hzw
* @Time: 2018/4/19 14:48
* @Description: 改進:版本2中由於serverSocket.accept()只執行一次,所以只能一對一通訊,一對多通訊必須有多個socket,並存儲在server屬性中作為集合儲存
* ReceiveThread將獲取的socket存入集合中,send都遍歷這個集合,實現群發功能
* 但是由於阻塞,所以一個執行緒不能處理多個socket,所以必須一個執行緒處理一個socket,建立執行緒的時候必須傳入socket,main中每次接收一個,就建立對應的接收執行緒
* 群發訊息流程是建立對應的接收執行緒後,將socket加入集合,遍歷集合socket,給每個回話傳送訊息,而且輸入scanner只輸入一次,所以在main中輸入
* 由於這個輸入會阻塞,後面有連線到來的時候服務端accept執行不到,所以將輸入做成執行緒,防止阻塞.
*/
@SuppressWarnings("all")
public class ChatServer {
private ServerSocket serverSocket;
private List<Socket> socketList = new ArrayList<>();
public ChatServer(){
try {
serverSocket = new ServerSocket(8889);
} catch (IOException e) {
e.printStackTrace();
}
}
public void start(){
}
public static void main(String[] args){
ChatServer chatServer = new ChatServer();
while (true){
try {
Socket socket = chatServer.serverSocket.accept();
chatServer.socketList.add(socket);
System.out.println("新的連線" + socket.getPort());
Thread receiveThread = new Thread(new ReceiveThread(socket));
receiveThread.start();
SendMessage sendMessage = new SendMessage(chatServer.socketList);
Thread thread = new Thread(sendMessage);
thread.start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static class SendMessage implements Runnable{
private List<Socket> socketList;
public SendMessage(List<Socket> socketList){
this.socketList = socketList;
}
@Override
public void run() {
Scanner scanner = new Scanner(System.in);
String s = scanner.nextLine();
for (Socket socket1 : socketList) {
Thread sendThread = new Thread(new SendThread(socket1, s));
sendThread.start();
}
}
}
public static class SendThread implements Runnable{
private Socket socket;
private String s;
public SendThread(Socket socket){
this.socket = socket;
}
public SendThread(Socket socket, String s){
this.socket = socket;
this.s = s;
}
@Override
public void run() {
try {
OutputStream outputStream = socket.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(outputStream);
PrintWriter pw = new PrintWriter(osw, true);
pw.println(s);
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static class ReceiveThread implements Runnable{
private Socket socket;
public ReceiveThread(Socket socket){
this.socket = socket;
}
@Override
public void run() {
try {
InputStream inputStream = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(inputStream);
BufferedReader br = new BufferedReader(isr);
while (true){
System.out.println(br.readLine());
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* @Author: Hzw
* @Time: 2018/4/19 14:49
* @Description:
*/
@SuppressWarnings("all")
public class ChatClient {
private Socket socket;
public ChatClient(){
try {
socket = new Socket("127.0.0.1", 8889);
} catch (IOException e) {
e.printStackTrace();
}
}
public void start(){
Thread sendThread = new Thread(new SendThread());
Thread receiveThread = new Thread(new ReceiceThread());
sendThread.start();
receiveThread.start();
}
public static void main(String[] args){
ChatClient chatClient = new ChatClient();
chatClient.start();
}
public class SendThread implements Runnable{
@Override
public void run() {
try {
OutputStream outputStream = socket.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(outputStream);
PrintWriter pw = new PrintWriter(osw, true);
Scanner scanner = new Scanner(System.in);
while (true){
pw.println(scanner.nextLine());
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
public class ReceiceThread implements Runnable{
@Override
public void run() {
try {
InputStream inputStream = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(inputStream);
BufferedReader br = new BufferedReader(isr);
while (true){
System.out.println(br.readLine());
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}