学习完J2SE可以写一个简易的聊天软件来让刚学的知识融会贯通,代码注释的很详细哦!

开发版本历程:

V0.1:客户端实现一个界面

V0.2:客户端界面有输入框和显示框的界面

V0.3:客户端关闭按钮可以关闭窗口

V0.4:客户端按回车后输入框的文字显示在显示框

V0.5:服务端能够起一个服务监听某端口

V0.6:客户端能够连接到服务器端

V0.7:客户端发一条消息,服务端能够接收到

V0.8:服务器端能到接收多条来自客户端的消息,改善V0.7的只能接受一条消息

V0.9:客户端关闭后,服务器端采取相应的措施,是服务器端不报错

V1.0:服务器端可以连接多个客户端,并且可以接收到来自每个客户端发送的消息

V1.1:服务器端把接收到每个客户端的消息发送出去

V1.2:每个客户端都能接收来自服务器的数据,并显示在显示框

V1.3:检查一些异常并修复(下面的代码就是这个版本)

注:代码还有很多改进的地方,这只是一个简易的版本

聊天服务器端代码:

import java.io.*;

import java.net.*;

import java.util.*;

public class ChatServer {

boolean started = false;

ServerSocket ss = null;

List clients = new ArrayList();

public static void main(String[] args){

new ChatServer().start(); //不能直接这样调用start()

}

public void start(){

try {

ss = new ServerSocket(8888); //在端口8888建立监听

started = true; //建立监听成功令此变量为真

}catch (SocketException e){

System.out.println("端口使用中。。。");

System.out.println("请关掉相关程序!");

System.exit(0);

}catch (IOException e) {

e.printStackTrace();

}

try{

while(started){

Socket s = ss.accept(); //***重要***若此处报错,尝试用360进行LSP修复

Client c = new Client(s); //每接受一个客户端就会new一个线程

System.out.println("a client connected");

new Thread(c).start(); //启动线程,start()方法只是启动线程,而线程中的run()方法这是实现此线程功能的代码

clients.add(c);

}

}catch (IOException e) {

e.printStackTrace();

}finally{

try {

ss.close();

} catch (IOException e) {

e.printStackTrace();

}

}

}

//定义一个线程内部类

class Client implements Runnable{

private Socket s;

private DataInputStream dis = null;

private DataOutputStream dos = null;

private boolean bConnected = false;

public Client(Socket s){

this.s=s;

try {

dis = new DataInputStream(s.getInputStream());

dos = new DataOutputStream(s.getOutputStream());

bConnected = true; // 有一个客户端连上后另此变量为真

} catch (IOException e) {

e.printStackTrace();

}

}

public void send(String str){

try {

dos.writeUTF(str);

} catch (IOException e) {

clients.remove(this);//防止有一个客户端退出了,其他客户端还在发消息,此时List里面还有这个退出的客户端,服务器就会报错

System.out.println("对方退出了,已经从List里面去除了!");

}

}

public void run() {

try {

while (bConnected) {

String str = dis.readUTF(); //readUTF()是一个阻塞式的,main方法执行到此处就一直一行一行的读,程序停在此处

System.out.println(str);

for(int i = 0; i < clients.size(); i++){

Client c = clients.get(i);

c.send(str);

}

}

}catch(EOFException e){

System.out.println("Client closed!");

}catch (IOException e) {

e.printStackTrace();

}finally{

try {

if(dis != null) dis.close();

if(dos != null) dos.close();

if(s != null) s.close();

} catch (IOException e1) {

e1.printStackTrace();

}

}

}

}

}

聊天客户端代码:

import java.awt.*;

import java.awt.event.*;

import java.io.*;

import java.net.*;

//客户端ChatClient

public class ChatClient extends Frame{

//响应他的事件,需要去访问他的内容,所以定义为成员变量

TextField tfTxt = new TextField();

TextArea taContent = new TextArea();

Socket s = null;

DataOutputStream dos = null;

DataInputStream dis = null;

private boolean bConnected = false;

Thread tRecv = new Thread(new RecvThread());

public static void main(String[] args) {

new ChatClient().launchFrame();

}

//运行客户端窗口的方法

public void launchFrame(){

this.setLocation(400,300);

setSize(300,300);

add(tfTxt,BorderLayout.SOUTH); //BorderLayout为Frame默认布局管理器。调用其他应调用setLayout(某个布局管理器对象)

add(taContent,BorderLayout.NORTH);

pack(); //如果没有pack();则两个控件中有空的部分

//使用匿名类添加窗口的事件监听器,注意WindowAdapter()的使用,windowClosing将要关闭窗口

this.addWindowListener(new WindowAdapter() {

public void windowClosing(WindowEvent e) {

disconnect();

System.exit(0);

}

});

//把监听器添加在文本框上,此时回车直接返回对象的信息,不需要添加Enter的KeyListener

tfTxt.addActionListener(new TFListener());

setVisible(true);

connect();

tRecv.start();

}

public void connect(){

try {

s = new Socket("127.0.0.1",8888);

dos = new DataOutputStream(s.getOutputStream());

dis = new DataInputStream(s.getInputStream());

System.out.println("connected!");

bConnected = true;

} catch (UnknownHostException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

}

}

public void disconnect() {

try {

dos.close();

dis.close();

s.close();

} catch (IOException e) {

e.printStackTrace();

}

}

private class TFListener implements ActionListener {

public void actionPerformed(ActionEvent e) {

String str = tfTxt.getText().trim(); //String里面的方法trim()去掉两边的空格

tfTxt.setText(""); //设置一个空字符串,让文本框里面的内容为空

try {

dos.writeUTF(str);

dos.flush();

} catch (IOException e1) {

e1.printStackTrace();

}

}

}

private class RecvThread implements Runnable {

@Override

public void run() {

try {

while (bConnected) {

String str = dis.readUTF();

taContent.setText(taContent.getText() + str + '\n');

}

} catch(SocketException e){

System.out.println("退出了,bye!");

} catch (IOException e) {

e.printStackTrace();

}

}

}

}

java实现简易聊天窗口先运行服务器还是客户端_一个简易聊天功能的服务器端和客户端源码...相关推荐

  1. java愤怒的小鸟代码_AngryBird 愤怒的小鸟,java源代码,可直接运行,非常好的一个 Develop 238万源代码下载- www.pudn.com...

    文件名称: AngryBird下载 收藏√  [ 5  4  3  2  1 ] 开发工具: Java 文件大小: 18192 KB 上传时间: 2013-12-23 下载次数: 5 提 供 者: 林 ...

  2. java毕业设计——基于java+JSP+sqlserver的Smart系统-题库及试卷管理模块设计与实现(毕业论文+程序源码)——学生信息管理系统模板2

    基于java+JSP+sqlserver的Smart系统-题库及试卷管理模块设计与实现(毕业论文+程序源码) 大家好,今天给大家介绍基于java+JSP+sqlserver的Smart系统-题库及试卷 ...

  3. java计算机毕业设计HTML5“忆红楼梦之味”网站设计与实现MyBatis+系统+LW文档+源码+调试部署(2)

    java计算机毕业设计HTML5"忆红楼梦之味"网站设计与实现MyBatis+系统+LW文档+源码+调试部署(2) java计算机毕业设计HTML5"忆红楼梦之味&quo ...

  4. 写了个Android聊天客户端框架,基本聊天功能、数据库、服务器都有。大家可以看一看。已经开源

    写了个Android聊天客户端框架,基本聊天功能.数据库.服务器都有.大家可以看一看.已经开源(希望两个手机通信的话,改一下pushid就可以) 几点说明: 1:包含的基本功能.: 1.1比如gif动 ...

  5. java计算机毕业设计Vue.js网上书城管理系统设计与实现服务端MyBatis+系统+LW文档+源码+调试部署

    java计算机毕业设计Vue.js网上书城管理系统设计与实现服务端MyBatis+系统+LW文档+源码+调试部署 java计算机毕业设计Vue.js网上书城管理系统设计与实现服务端MyBatis+系统 ...

  6. 基于JAVA社区微服务平台小程序服务器端计算机毕业设计源码+系统+lw文档+部署

    基于JAVA社区微服务平台小程序服务器端计算机毕业设计源码+系统+lw文档+部署 基于JAVA社区微服务平台小程序服务器端计算机毕业设计源码+系统+lw文档+部署 本源码技术栈: 项目架构:B/S架构 ...

  7. 编程语言用 Java 开发一个打飞机小游戏(附完整源码)

    编程语言用 Java 开发一个打飞机小游戏(附完整源码) 上图 写在前面 技术源于分享,所以今天抽空把自己之前用java做过的小游戏整理贴出来给大家参考学习.java确实不适合写桌面应用,这里只是通过 ...

  8. 仿微信的网络聊天室项目开发【完整源码讲解,Java一年工作经验面试题

    /*使滚动条置于文本框最下端*/ infoWindow.setSelectionStart(infoWindow.getText().length());JScrollBar jSBInfo = jS ...

  9. idea命令行运行多个客户端_推荐一款神仙颜值的 Redis 客户端工具,开源啦

    日常开发过程中,项目常常都会使用Redis来做缓存或者Session服务器,为了更直观方便,开发者常常会使用一些可视化工具,如 Redis Desktop Manager.Redis Clent等,但 ...

最新文章

  1. Numpy、TensorFlow和Keras函数输入参数axis理解
  2. ISME: 中科院南京土壤所褚海燕组揭示关键菌群的生物多样性决定作物产量
  3. 【白话机器学习】算法理论+实战之PageRank算法
  4. JavaScript——自定义对话框
  5. 网络基础:Ping命令的7种基础用法,掌握了秒变大神!
  6. python多态_Python基础入门18节-第十六节 面向对象如何理解多态
  7. TCP/IP协议详解 卷一(阅读指导)
  8. Mysql执行计划的extra列及filesort祥析
  9. 学会使用context取消goroutine执行的方法
  10. SQL Server-【知识与实战V】视图
  11. 百度地图与 select下拉框的双向维护
  12. 图中提取数据再作图---GetData Graph Digitizer
  13. ERROR: Minimum supported Gradle version is 5.4.1. Current version is 5.1.1.
  14. 关于Socket的建立及连接
  15. 解决MobaXtem中使用vim不能复制到Windows
  16. 接口测试 - 构造伪数据/测试数据(Faker)
  17. pycharm如何增加运行时内存
  18. 奉劝大家不要再用刷流量软件刷新浪博客等级了
  19. 无法连接到已配置的开发web服务器_Power BI 报表服务器极简安装指南
  20. QT 此操作至少需要一个处于启用状态的有效资料档案库

热门文章

  1. git比较当前工作区和之前提交的内容差异
  2. SAP CRM呼叫中心的邮件发送实现 - Function module CRM_EMAIL_SEND_EMAIL
  3. gateway response annotation comes first, then project folder one
  4. Hybris commerce的promotion rule里的固定折扣功能
  5. attachRouteMatched analysis
  6. 阿里云的很多域名没有办法进行实名认证了吗
  7. 使用jMeter的regular expression extract提取SSO form的XSRF protection token
  8. object overview page打开后白屏问题分析
  9. GT_HEADERGUID_LIST
  10. AOP原理学习之How is JdkDynamicAopProxy generated