说明
今年因为疫情缘由只能在家里学习,今年学校有一门很重要的课程《面向对象》,学习了java中的编程思想、多线程、JML、UML等等东西,为了检验本身学习得好很差,再加上据说 java 很适合 socket 编程,而且阿里云的服务器一年才九十多块钱,我就决定(其实以上都不是主要缘由,主要缘由就是考完试在家闲的发慌)决定搭建一个多人在线聊天室,而且从中也能够学习 Swing、socket 等等。java
后面代码中全部GUI界面布局的内容,参见我以前的一篇博客 Swing的简要学习记录 。git
本次实现的聊天室功能比较简单,主要实现的功能以下:github
- 带有优美的 GUI界面(
才怪); - 在服务器容许的压力下支持多人实时聊天;
- 支持帐户登陆功能(不支持注册功能,也就是服务器端预先设好了帐号)
如下是或许下一次要改进的内容:编程
- 实现注册功能;
- 实现单人聊天;
- 实现好友功能
Socket及java编程方法
socket(套接字)是计算机之间进行通讯的一种约定。若是学过操做系统应该会知道,进程之间的通讯(IPC)包括管道、FIFO、共享内存、信号量机制等等,这里socket就是一种可用于不一样计算机的进程之间的通讯机制,用来解决网络通讯问题。服务器
socket的通讯基于TCP/IP协议,用(ip地址,协议,端口号)惟一标识某一个主机中的某一个进程,socket通讯的数据传输方式包括两种:SOCK_STREAM(流套接字,基于TCP协议,特色是不易出错)和SOCK_DGRAM(数据报套接字,基于UDP协议,特色是速度快)。java中的socket编程应该主要是基于TCP协议的。TCP链接时有什么三次握手创建链接(connect)、四次握手断开链接(close),这些说实话具体过程我都不了解。网络
我只知道 java 中应该怎么写(注意里面的Macro是我本身定义的一个类,能够忽略):多线程
- 服务器端:
// 创建socket服务 ServerSocket serverSocket = new ServerSocket(Macro.port); // 这句话的意思是,一直等待客户端链接,一旦链接成功就返回一个socket Socket socket = serverSocket.accept();
主要的socket链接创建其实就这两个,通常实现时会每当有客户端链接时,新建一个线程去处理。socket
- 客户端:
// 创建一个与serverIP服务器,port端口的socket链接 try { socket = new Socket(Macro.serverIp, Macro.port); } catch (Exception e) { e.printStackTrace(); }
就这样服务器和客户端的socket链接就如此方便地创建好了!函数
- 经常使用文件流:
BufferedReader bufferedReader = null; // 这个是socket中的输入流 PrintWriter printWriter = null; // 这个是socket中的输出流 try { bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream())); printWriter = new PrintWriter(new OutputStreamWriter(socket.getOutputStream())); } catch (Exception e) { e.printStackTrace(); }
这些文件流跟本地的标准输入输出以及文件操做其实差很少,就是写入读出这些操做。布局
而后就能够服务器和客户端就能够经过这两个流进行通讯了。
功能结构
共享类
这是服务器和客户端共享的类,这些类无论在打包服务器的jar或者客户端的jar时都应该包括在内,这些类包括Macro和Message,前者定义了一些通讯中encode和decode的规则,以及服务器ip、端口号等等,后者用于双方发送消息的载体。
- Macro类:定义通讯规则(包括对LOGIN请求的加密和解密、LOGOUT请求的加密和解密、MESSAGE的加密和解密、登陆是否成功信号的定义)、服务器相关信息、一些信号的宏定义等等;
- Message类:定义了用户发送的一个message须要包含的信息,有:发送者、发送时间、发送内容。
服务器端
服务器端处理用户登陆登出请求、维护当前登陆状态、维护用户帐号密码信息、处理message发送请求,而且要支持多用户服务,主要包含的类以下:
- server类:一直运行,初始加载Info类和MessageSend类,而且一直调用
serverSocket.accept()
进行socket链接监听,一但有socket链接成功,新建一个serverThread线程进行socket通讯。 - serverThread类:这个类与Info类和MessageSend类有关联关系,用于与socket通讯。这个类须要一直读入用户请求,而且支持三种请求:
- LOGIN请求:经过Info类判断该用户是否合法,密码是否正确,若是正确就在MessageSend中设定该用户在线,而且经过socket返回登陆成功信号;
- LOGOUT请求:直接在MessageSend中设定该用户注销(不在线);
- MESSAGE请求:MessageSend中调用函数,给全部在线用户发送该message。
- Info类:记录用户帐号密码信息,提供帐号密码是否正确的服务。
- MessageSend类:记录在线用户(username)以及与他们socket通讯中的PrintWriter,实现发送Message的功能。
客户端
客户端用于用户登陆以及聊天,主要实现了两个GUI界面(登陆界面和聊天界面),包括的类以下:
- Client类:调用登陆界面。
- Login类:实现登陆界面的JFrame,与服务器创建链接,每当进行登陆操做时向服务器发送登陆请求,而后读取登陆是否成功的信息,若是成功调用Dialog类运行而且向之传送socket信息,而后销毁本身。
- Dialog类:实现聊天界面的JFrame,经过socket与服务器通讯,每当进行发送操做时,打包输入框中的文字为Message,而后发送给服务器。而且一直读入服务器传来的数据,进行decode而后显示在聊天框中。还要对窗体的关闭键进行监听,关闭窗体时向服务器发送LOGOUT请求,而且关闭当前的socket,而后销毁本身。
效果展现



代码
详细的代码和运行方法,参见 这里 。