package socket;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Arrays;
import java.util.Scanner;
/**
-
Copyright: Copyright © 2019
-
@ClassName: Servlet.java
-
@Description: 聊天室服务端
-
@Version: v1.0.0
-
@Author: Abelard
-
@Date: 2019年7月4日 下午2:05:28
/
public class Servlet {
/- 运行在服务端的ServerSocket 主要有两个作用: 1.向系统申请服务端口,客户端就是通过这个端口与服务端建立链接
- 2.监听该端口,这样客户端建立连接时,ServerSocket就会自动实例化一个socket 用于与该客户端进行数据交互
/
private ServerSocket server;
/*-
用来存放所有客户端输出流的共享数组
-
内部类可以访问外部类的属性,因此在Server上定义这样一个数组
-
可以保存所有ClientHandler需要互访的输出流,做到他们之间共享数据使用
/
private PrintWriter[] allOut = {};
/ -
构造方法用于初始化服务端
/
public Servlet() {
try {
/
* 实例化ServerSocket时传入打开的服务端口 如果该端口被其他程序使用,则实例化时会抛出异常
*/
System.out.println(“正在启动服务器…”);
server = new ServerSocket(8088);
System.out.println(“服务器启动完毕”);} catch (Exception e) {
e.printStackTrace();
}
}
/*
-
服务器开始工作
*/
public void start() {try {
/*
* ServerSocket提供方法 Socket accept() 该方法是一个阻塞方法,调用后开始等待客户端
* 连接,当一个客户端连接后该方法返回一个Socket实例 通过这个Socket实例可以与客户端交互
*
* 多次调用accept方法可以接收多个客户端连接
*/
Socket socket;
while (true) {
System.out.println(“等待客户端连接…”);
socket = server.accept();
System.out.println(“客户端连接”);
//启动一个线程来处理该用户端交互
ClientHandler clientHandler = new ClientHandler(socket);
Thread thread = new Thread(clientHandler);
thread.start();
}
} catch (Exception e) {e.printStackTrace();
}
}
public static void main(String[] args) {
Servlet servlet = new Servlet();
servlet.start();
}
//创建线程任务
private class ClientHandler implements Runnable{
private Socket socket;
//获取远端计算机地址
private String host;public ClientHandler(Socket socket) { this.socket = socket; InetAddress address = socket.getInetAddress(); host = address.getHostAddress(); } @Override public void run() { /* * 通过该输入流来读取到内容是远端计算机发送过来的数据 */ try { InputStream is = socket.getInputStream(); InputStreamReader isr = new InputStreamReader(is, "utf-8"); BufferedReader br = new BufferedReader(isr); /** * 通过Socket获取输出流,用于将消息发送给当前的客户端 * */ OutputStream out = socket.getOutputStream(); OutputStreamWriter ow = new OutputStreamWriter(out); BufferedWriter bw = new BufferedWriter(ow); PrintWriter pw = new PrintWriter(bw,true); /* * 将对应客户端的输出流存入到共享数组中以便于其他的clienthandler可以访问到 * */ //1.对allout扩容 allOut = Arrays.copyOf(allOut, allOut.length+1); allOut[allOut.length-1] = pw; String line = null; while ((line = br.readLine())!=null) { /* * 接收客户端 */ System.out.println(host+":" + line); //将消息返回给所有客户端 for(int i=0;i<allOut.length;i++) { allOut[i].println(line); } if(line.equals("exit")) { System.out.println("程序结束"); break; } } }catch (IOException e) { e.printStackTrace(); } }
}
}
客户端
package socket;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;
import java.util.Scanner;
/**
-
Copyright: Copyright © 2019
-
@ClassName: Client.java
-
@Description: 聊天室客户端
-
@Version: v1.0.0
-
@Author: Abelard
-
@Date: 2019年7月4日 下午2:05:17
/
public class Client {
/*- java.net.Socket套接字 封装了tcp协议的通讯细节,使得我们利用TCP通讯 以流的读写操作形式完成
- 套接字:源IP地址和目的IP地址以及源端口号和目的端口号的组合称为套接字
*/
private Socket socket;
private String host;
/*-
构造方法,用于初始化客户端
/
public Client() {
try {
/
* 实例化Socket时需要传入两个参数: 1.服务端的地址 2.服务端打开的端口号
* 这里实例化Socket的过程就是通过给定 地址链接服务端的过程,若链接不成功 构造方法会抛出异常 通过IP地址我们可以找到网络上服务端
* 所在的机器,通过端口就可以找到运行在 服务端计算机上的服务端应用程序
*/
System.out.println(“正在链接服务器…”);
socket = new Socket(“localhost”, 8088);
System.out.println(“已连接服务端”);} catch (Exception e) {
e.printStackTrace();
}
}
/*
-
客户端开始工作方法
*/
public void start() {
try {
InetAddress address = socket.getInetAddress();
host = address.getHostAddress();OutputStream out = socket.getOutputStream(); OutputStreamWriter osw = new OutputStreamWriter(out, "utf-8"); BufferedWriter bw = new BufferedWriter(osw); PrintWriter pWriter = new PrintWriter(bw, true); Scanner scanner = new Scanner(System.in); /** * 通过socket流获取输入流,读取客户端发送过来的消息 */ InputStream is = socket.getInputStream(); InputStreamReader isr = new InputStreamReader(is, "utf-8"); BufferedReader br = new BufferedReader(isr); String line = null; while (true) { /* * 跟服务端对话 */ System.out.println("请输入你要对服务端说的话"); String seke = scanner.next(); pWriter.println(seke); line = br.readLine(); System.out.println(host+"说:"+line); }
}catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
Client client = new Client();
client.start();
}
}