事情是这样的,俺们这学期学java面向对象,实验课的网络通讯这块,让我们写一个基于Socket的聊天室,大家可以广播其他在线的用户,并发送数据,这里要求使用多线程写。话不多说,我们先看一下实验现象。
这是服务器端的现象
接下来我们说一下程序的大概思路,
服务器创建线程,并且线程在创建完毕之后一直使用socket = serverSocket.accept();函数去接收客户端的连接请求,注意这里的函数是阻塞函数,也就是说在创建完线程之后,在没有连接成功的情况下是不会继续往下运行的,这个坑请记住!
并且将已经连接的socket连接加入我们的队列中,在接收到消息的时候,需要历遍发送数据至每个连接中。
在客户端软件中,我们只需要进行连接发送以及接收即可,我们只需要创建一个线程用来不断的接收即可。
接下来是代码展示。
server1代码
package com.company.javaHK.src;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
public class exp3_server {
public static ServerSocket serverSocket = null;
public static List<Socket> SocketList = new ArrayList<>();
public static void main(String[] args) throws IOException {
serverSocket = new ServerSocket(10006);
System.out.println("服务器已经准备好接收数据了");
for(int i = 0;i<5;i++){
AddClientsThread addClientsThread = new AddClientsThread();
addClientsThread.start();
}
}
static class AddClientsThread extends Thread {
Socket socket = null;
Boolean flag = true;
public Socket getSocket() {
return socket;
}
@Override
public void run() {
while (true) {
try {
//如果要为多个客户端服务,让服务器接收的客户端请求(Socket socket=serverSocket.accept())
// 处于循环中,其实就相当于有N个服务器,当然就可以与n个用户端通信
socket = serverSocket.accept();
SocketList.add(socket);
System.out.println("连接成功");
} catch (IOException e) {
e.printStackTrace();
}
while (true) {
try {
if(socket.isClosed()){
this.flag = false;
SocketList.remove(this.socket);
System.out.println("当前线程已经结束");
}
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
while (flag){
String temp = br.readLine();
System.out.println(temp);
for(int i=0;i<SocketList.size();i++){
System.out.println("当前在线人数:"+SocketList.size()+"人");
Socket tempSocket = SocketList.get(i);
if(tempSocket!=socket){
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(tempSocket.getOutputStream()));
//send message
bw.write(temp+"\n");
bw.flush();
}
}
//如果数据不为空的时候就是数据已经收取到
if (!temp.equals("")) {
break;
}
}
//他会关闭我的socket
//br.close();
} catch (IOException e) {
//如果下线则删除该代码
System.out.println("Socket is closed,当前线程已经结束");
this.flag = false;
SocketList.remove(this.socket);
}
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
}
clinent1代码
package com.company.javaHK.src;
import java.io.*;
import java.net.Socket;
import java.util.Scanner;
public class exp3_client {
public static void main(String[] args) throws IOException {
Scanner scanner = new Scanner(System.in);
Socket soc = new Socket("localhost", 10006);
ClientRecThread clientRecThread = new ClientRecThread(soc);
clientRecThread.start();
System.out.print("请输入你的登录名:");
String name = scanner.nextLine();
PrintStream ps = new PrintStream(soc.getOutputStream());
ps.print(name + "上线了!!\n");
System.out.print("打下字符,并按下回车即可发送数据");
String input = scanner.nextLine();
while (!input.equals("exit")) {
System.out.print("打下字符,并按下回车即可发送数据");
ps = new PrintStream(soc.getOutputStream());
input = name + ":" + input + "\n";
ps.print(input);
input = scanner.nextLine();
}
ps.close();
soc.close();
}
}
class ClientRecThread extends Thread {
public Socket socket;
public ClientRecThread(Socket socket){
this.socket = socket;
}
public void receiveMethod() {
try {
//读取数据
BufferedReader binBufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
do {
String temp = binBufferedReader.readLine();
if (temp == null) {
break;
}
System.out.println("收到消息:" + temp);
System.out.print("打下字符,并按下回车即可发送数据");
} while (true);
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void run() {
while (true) {
receiveMethod();
try {
Thread.sleep(20);
} catch (InterruptedException e) {
e.printStackTrace();
break;
}
}
}
}
clinet2代码
package com.company.javaHK.src;
import java.io.*;
import java.net.Socket;
import java.util.Scanner;
public class exp3_client_1 {
public static void main(String[] args) throws IOException {
Scanner scanner = new Scanner(System.in);
Socket soc = new Socket("localhost", 10006);
ClientRecThread clientRecThread = new ClientRecThread(soc);
clientRecThread.start();
System.out.print("请输入你的登录名:");
String name = scanner.nextLine();
PrintStream ps = new PrintStream(soc.getOutputStream());
ps.print(name + "上线了!!\n");
System.out.print("打下字符,并按下回车即可发送数据");
String input = scanner.nextLine();
while (!input.equals("exit")) {
System.out.print("打下字符,并按下回车即可发送数据");
ps = new PrintStream(soc.getOutputStream());
input = name + ":" + input + "\n";
ps.print(input);
input = scanner.nextLine();
}
ps.close();
soc.close();
}
}
class ClientRecThread_1 extends Thread {
public Socket socket;
public ClientRecThread_1(Socket socket){
this.socket = socket;
}
public void receiveMrthod() {
BufferedReader br = null;
try {
//读取数据
BufferedReader binBufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
do {
String temp = binBufferedReader.readLine();
if (temp == null) {
break;
}
System.out.println("收到消息: " + temp);
} while (true);
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void run() {
while (true) {
receiveMrthod();
try {
Thread.sleep(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
break;
}
}
}