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();
}
}
}
}