基于Socket的多人聊天

  • 思路
    • 服务器端
      • 主线程代码
      • 注册线程代码
      • 轮询线程代码
    • 客户端

思路

网络上的聊天本质上属于数据的交互,一个服务方负责接收客户端发来的信息,并进行进一步处理。因为此次实验是在本地实验,ip地址相同,所以封给stocket加了一个名字用于区别。

服务器端

服务器端的设计,采用多线程的方式。
主线程:负责监听客户端的连接,当监听到一个匹配的客户端时,调用注册线程将该客户端加入map集合中。

主线程代码

public class Server {//存储客户端static volatile  Map<String,nameSocket> socketMap = new HashMap<String,nameSocket>();//存储客户端姓名,将用该集合进行轮询操作static volatile List<String> names = new ArrayList<>();public static void main(String[] args) {try {ServerSocket serverSocket = new ServerSocket(10086);//启动轮询线程new Thread(new lunxun()).start();//等待客户端连接while(true){//包装客户端nameSocket ns = new nameSocket();ns.setSocket(serverSocket.accept());//启动注册线程new Thread(new login(ns)).start();}} catch (Exception e) {e.printStackTrace();}}
}

注册线程:线程会给客户端进行一次交互,询问姓名,得到客户端输入的姓名后将该客户端进行保存,线程执行完毕后会自然销毁。

注册线程代码

class login implements Runnable{//包装的客户端private nameSocket ns;//用于接收客户端姓名private String str = null;public login(nameSocket ns) {this.ns = ns;}@Overridepublic void run() {synchronized (Server.class){try {//向客户端发送信息OutputStream outputStream = ns.getSocket().getOutputStream();outputStream.write("来自服务器的消息:请输入您的用户名!".getBytes());//客户端时读取一行数据,需要发送"\n"结束outputStream.write("\n".getBytes());outputStream.flush();//读取客户端发送的消息BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(ns.getSocket().getInputStream()));if((str = bufferedReader.readLine())!=null){ns.setName(str);Server.names.add(str);Server.socketMap.put(str,ns);}outputStream.write(("来自服务器的消息:欢迎您"+str).getBytes());outputStream.write("\n".getBytes());outputStream.flush();} catch (Exception e) {if(e.getClass() == SocketException.class){//如果异常异常类型匹配,代表客户端断开连接。if(str!=null){//有名字则删除客户端System.out.println(str+"下线了!");Server.names.remove(str);Server.socketMap.remove(str);}else {System.out.println("不知名的用户下线了!");}}else {e.printStackTrace();}}}}
}

轮询线程:线程负责循环读取map集合中的客户端,如果客户端有消息,将启用一个聊天线程负责输出。

轮询线程代码

class lunxun implements Runnable{//正在轮询到的客户端姓名private String na;private int num = 0;@Overridepublic  void  run() {while(true){try {//加上锁synchronized (Server.class){//用变量num的增长实现轮询。for (int i = 0;i<Server.names.size();i++){na = Server.names.get(num%Server.names.size());if(num<Server.names.size()){num++;}else {num = 1;}//给客户端设置超时时间,出了异常会跳出循环Server.socketMap.get(na).getSocket().setSoTimeout(10);InputStreamReader inputStreamReader = new InputStreamReader(Server.socketMap.get(na).getSocket().getInputStream());//约定在发送的数据前多加一个字符,保证数据的完整性。if (inputStreamReader.read()!=-1){new Thread(new liaotian(na,new BufferedReader(inputStreamReader))).start();}}}} catch (Exception e) {if(e.getClass() == SocketException.class){//异常类型相等则表示客户端下线,删除客户端。System.out.println(na+"下线了!");Server.names.remove(na);Server.socketMap.remove(na);}else if (e.getClass() == SocketTimeoutException.class){//超时异常不做处理}else {e.printStackTrace();}}}}
}

聊天线程:负责打印需要输出的客户端数据流,该线程在执行结束后将自然销毁。

class liaotian implements Runnable{//客户端姓名private String name;//数据流private BufferedReader bufferedReader;public liaotian(String name, BufferedReader bufferedReader) {this.name = name;this.bufferedReader = bufferedReader;}@Overridepublic void run() {try{System.out.println(name+":"+bufferedReader.readLine());}catch(Exception e){e.printStackTrace();}}
}

客户端

在链接上服务端时,先与服务端进行一次录入姓名的交互,接着进入循环读取控制台的信息并发送至服务端。

public class khd {public static void main(String[] args) {try {String str = null;Socket socket = new Socket(InetAddress.getByName("127.0.0.1"),10086);Scanner scanner = new Scanner(System.in);//获取输出流PrintStream printStream = new PrintStream(socket.getOutputStream());//获取输入流BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));//与服务器第一次交互开始------(有些臃肿)if ((str = bufferedReader.readLine())!= null){System.out.println(str);}printStream.write(scanner.nextLine().getBytes());printStream.write("\n".getBytes());printStream.flush();if ((str = bufferedReader.readLine())!= null){System.out.println(str);}//与服务器第一次交互结束------while(true){//与服务端约定在数据前加上一个字符printStream.write(("s"+ scanner.nextLine()+"\n").getBytes());printStream.flush();}} catch (Exception e) {e.printStackTrace();}}
}

效果:

基于Socket的多人聊天雏形(java实现)相关推荐

  1. java socket多人聊天室_如何运用Java socket实现多人聊天室功能

    如何运用Java socket实现多人聊天室功能 导语:如何运用Java socket实现多人聊天室功能呢?下面是小编给大家提供的代码实现,大家可以参考阅读,更多详情请关注应届毕业生考试网. 目录结构 ...

  2. java socket多人聊天_如何运用Java socket实现多人聊天室功能

    导语:如何运用Java socket实现多人聊天室功能呢?下面是小编给大家提供的代码实现,大家可以参考阅读,更多详情请关注应届毕业生考试网. 目录结构: ChatClient: package com ...

  3. 基于Python的多人聊天室的设计与实现

    基于Python的多人聊天室的设计与实现 摘要  本文介绍了基于即时通讯的Python实现web版多人聊天室的设计和实现.这个系统利用了多种先进的技术,如Django.Channels.WebSock ...

  4. 基于python面向对象多人聊天室

    基于python面向对象多人聊天室 1.项目环境 项目名称:多人聊天室 项目模式:C/S 开发环境:win10+python3.8+pycharm 所需知识:python GUI编程,多线程编程,网络 ...

  5. 基于socket.io的web聊天室

    基于socket.io的web聊天室 一. 项目介绍 该项目使用node.js作为后端服务器框架,并利用socket.io来实现web聊天室功能.socket.io是由 JavaScript 实现的基 ...

  6. 【Linux网络编程】基于UDP实现多人聊天室

    文章目录 一.UDP的概念 1.1 UDP 1.2 UDP特点 二. 采用UDP实现多人聊天室原因 三.多人聊天室项目功能 四.实现多人聊天室项目流程分析 4.1 前期准备 4.1.1 定义结构体 4 ...

  7. Linux下基于socket和多线程的聊天室小程序

    转载:http://blog.csdn.net/robot__man/article/details/52460733 要求:基于TCP编写,一个聊天室最多100人.  客户端:  1.用户需要登录, ...

  8. TCP多人聊天程序Java实现(群聊,私聊,在线用户,踢出用户)

    本程序在程序 https://blog.csdn.net/joffy/article/details/18079331 的基础是上添加了私聊,踢出用户两个功能. 由客户端和服务器端构成程序,程序借助J ...

  9. Python+Socket实现多人聊天室,功能:好友聊天、群聊、图片、表情、文件等

    一.项目简介 本项目主要基于python实现的多人聊天室,主要的功能如下: 登录注册 添加好友 与好友进行私聊 创建群聊 邀请/申请加入群聊 聊天发送图片 聊天发送表情 聊天发送文件 聊天记录保存在本 ...

最新文章

  1. div内实现文字左右循环滚动
  2. 数据挖掘工具weka使用
  3. 05.elasticsearch-index相关总结
  4. 森汉姆算法(AS3)-检测两点之间所经过的节点
  5. 计算机图画大赛作品六年级,打字能手显本领,电脑绘画展风采——记陆埠二小举行电脑绘画和电脑打字比赛...
  6. 查找算法:插值查找算法实现及分析
  7. 京东、宅急送的微服务实践分享(下)| 架构师小组交流会
  8. python爬虫哪个选择器好用_Python爬虫学习8-css选择器使用
  9. js时间差计算的几种方式
  10. visio 画箭头_visio2013中画箭头的具体操作步骤
  11. java熟人_英语中对各种不同程度关系的朋友是怎么表示的(就像汉语里有泛泛之交、熟人、朋友、死党之类的)?...
  12. HSV/HSB/HSL 色相、饱和度、亮度的色彩模型
  13. 栈内存和堆内存的区别
  14. sql查询最新时间的一条数据
  15. matlab学习-大小写字符转发
  16. java 读取mysql blob字段乱码
  17. h3c S2000-EA 交换机DHCP Snooping支持Option 82功能的配置
  18. android横向滑动换页,[转载]Android 左右滑动切换页面或Activity的效果实现
  19. Verilog实现Bresenham任意斜率直线
  20. mac pro 升级ssd_您可以在Mac中升级硬盘驱动器或SSD吗?

热门文章

  1. 作为一名数据科学家必备工具有哪些?
  2. linux 开机遇见unmount and run xfs_repair
  3. ICS Protocol Dissection
  4. 固件库应用之按键检测
  5. java pdfbox 合并PDF、PDF转图片、PDF插入图片
  6. or: union member ‘RTMP::RtmpStream::NalData::nal_data::StapA’ with non-trivial ‘RTMP::RtmpS
  7. 字符串比较的到底是什么?“abc“==“abc“?
  8. Oracle ADDM自动数据库诊断监视器
  9. html+css 实现导航栏二级菜单——气泡框
  10. 团购GPT-4 Plus!把价格打下来!