Java实现本地Socket通信(三)
今天任务较少也较为简单本节任务账号登录半成品可视化界面一、账号登陆我们知道账号输入操作是需要在客户端进行的所以这里我们需要在客户端封装登陆方法login在这里读取输入并传递给服务端账号信息public void login(OutputStream os){ Scanner scnew Scanner(System.in); System.out.println(请输入账号); String accountsc.nextLine(); byte[] acaccount.getBytes(); try { os.write(ac.length);//不可以发送字符串的长度必须发送字节的长度 os.write(ac); os.flush(); } catch (IOException e) { throw new RuntimeException(e); } }接着我们需要在服务端读取传递过来的信息用封装函数proLogein实现并返回读取到的用户名public String proLogein(Socket socket){ try { InputStream issocket.getInputStream(); int lenis.read(); byte[] msgsnew byte[len]; is.read(msgs); String userNamenew String(msgs); System.out.println(用户userName登录了); return userName; } catch (IOException e) { throw new RuntimeException(e); } }tips.这里proLogein方法应该在消息处理方法proClintMsg处创建线程时调用如下public void proClintMsg(Socket socket){ //注意循环速度太快导致cpu被占满io流根本没机会运行所以这里加一个println让cpu空闲下来 new Thread(()-{ //登录 //读取用户名 String UserNameproLogein(socket); ClientUser cunew ClientUser(UserName,socket); //保存ClientUser对象 SocketList.add(cu); while(true) { try { InputStream iscu.socket.getInputStream(); System.out.println(监听cu.socket.getPort()消息中);//顺序不对 String msgreceive(is); replyMsg(cu,msg); } catch (IOException e) { throw new RuntimeException(e); } } }).start(); }用户信息类Client内部定义了账号account用户名和套接字socket这里就不展示代码了至此用户登录的功能雏形便完成了二、实现界面可视化这里我们需要创建一个UI类ClientUI首先先创建窗口对象并调用内部函数设置相关参数尺寸、关闭方法、显示格式、布局等JFrame jfnew JFrame(聊天室); jf.setSize(500,600); jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//关闭 jf.setLocationRelativeTo(null);//居中显示 //默认边框布局随后添加相关组件最后记得设置可见文本显示JTextAreaJTextArea msgAreanew JTextArea();//支持多行显示所以不用jtext显示文字 JScrollPane scrollPanenew JScrollPane(msgArea);//滚动显示面板 jf.add(scrollPane, BorderLayout.NORTH);输入框JTestFieldJTextField msgFieldnew JTextField();//输入框 msgField.setPreferredSize(new Dimension(400,0)); msgField.setBackground(Color.LIGHT_GRAY); jf.add(msgField, BorderLayout.WEST);发送键JButtonJButton sendButtonnew JButton(发送); sendButton.setPreferredSize(new Dimension(100,0)); jf.add(sendButton, BorderLayout.EAST);tips.这里不要忘记为按钮添加监听方法下面是新版本的简便写法sendButton.addActionListener(e - sendMsg(msgArea,msgField)); //e相当于是内部类创建一个临时内部类可以直接调用本类中的函数不需要单独写一个监听类到这里界面基本就创建完成了接下来需要做的便是功能迁移三、功能迁移我们的代码大体上是不需要做什么改动的现在我们需要做的是读取可视化界面内输入框里的内容并让其显示在文本框上消息发送方法如下public void sendMsg(JTextArea msgArea,JTextField msgField){ String msgmsgField.getText(); //send(msg); System.out.println(发送中...); //设置到自己的界面上 msgArea.append(我msg\n); //发送消息 client.send(msg); }显示如下在showui中添加新线程new Thread(()-{ while(true) { String msgclient.readMsg(); // System.out.print(接收消息); // System.out.println(msg); // System.out.println(请输入); msgArea.append(msg\n); } }).start();四、完整代码·Clientimport java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.Socket; import java.util.Scanner; public class Client { //由于外部需要访问socket所以定义为全局变量 Socket socketnull; public void init(){ try { socketnew Socket(127.0.0.1,54321); login(socket.getOutputStream()); } catch (Exception e) { throw new RuntimeException(e); } } public void send(String message){ try { OutputStream ossocket.getOutputStream(); byte[] msgsmessage.getBytes(); int lenmsgs.length; os.write(len); os.write(msgs); os.flush(); } catch (Exception e) { throw new RuntimeException(e); } } public String readMsg(){ try { InputStream issocket.getInputStream(); int lenis.read(); byte[] msgsnew byte[len]; is.read(msgs); return new String(msgs); } catch (Exception e) { throw new RuntimeException(e); } } public void login(OutputStream os){ Scanner scnew Scanner(System.in); System.out.println(请输入账号); String accountsc.nextLine(); byte[] acaccount.getBytes(); try { os.write(ac.length);//不可以发送字符串的长度必须发送字节的长度 os.write(ac); os.flush(); } catch (IOException e) { throw new RuntimeException(e); } } }·ClientUIimport javax.swing.*; import java.awt.*; import java.util.Scanner; public class ClientUI extends JFrame { Client clientnew Client(); public void showUI(){ //先加载客户端 并进行登录 client.init(); JFrame jfnew JFrame(聊天室); jf.setSize(500,600); jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//关闭 jf.setLocationRelativeTo(null);//居中显示 //默认边框布局 JTextArea msgAreanew JTextArea();//支持多行显示所以不用jtext显示文字 // JTextPane msgPanenew JTextPane(msgArea); JScrollPane scrollPanenew JScrollPane(msgArea);//滚动显示 scrollPane.setPreferredSize(new Dimension(0,500)); JTextField msgFieldnew JTextField();//输入框 msgField.setPreferredSize(new Dimension(400,0)); msgField.setBackground(Color.LIGHT_GRAY); JButton sendButtonnew JButton(发送); sendButton.setPreferredSize(new Dimension(100,0)); //JLabel labelnew JLabel(当前状态); jf.add(scrollPane, BorderLayout.NORTH); jf.add(msgField, BorderLayout.WEST); jf.add(sendButton, BorderLayout.EAST); jf.setVisible(true); sendButton.addActionListener(e - sendMsg(msgArea,msgField));//e相当于是内部类创建一个临时内部类可以直接调用本类中的函数不需要单独写一个监听类 new Thread(()-{ while(true) { String msgclient.readMsg(); // System.out.print(接收消息); // System.out.println(msg); // System.out.println(请输入); msgArea.append(msg\n); } }).start(); } public void sendMsg(JTextArea msgArea,JTextField msgField){ String msgmsgField.getText(); //send(msg); System.out.println(发送中...); //设置到自己的界面上 msgArea.append(我msg\n); //发送消息 client.send(msg); } public static void main(String[] args) { ClientUI clientUInew ClientUI(); clientUI.showUI(); } }·ClientUserimport java.net.Socket; public class ClientUser { String account; Socket socket; public ClientUser(String account,Socket socket){ this.accountaccount; this.socketsocket; } public ClientUser(){ } }·Serverimport java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket; import java.util.ArrayList; public class Server { ServerSocket ssnull; ArrayListClientUser SocketListnew ArrayList(); public void init(){ try { ssnew ServerSocket(54321); } catch (IOException e) { throw new RuntimeException(e); } } public Socket listen(){ try { return ss.accept(); } catch (IOException e) { throw new RuntimeException(e); } } public void send(String message, OutputStream os){ try { //mission:通过os把这个消息发送出去 byte[] msgsmessage.getBytes(); int lenmsgs.length; os.write(len);//发送长度 os.write(msgs); os.flush(); } catch (IOException e) { throw new RuntimeException(e); } } public String receive(InputStream is){ try { int lenis.read(); byte[] msgsnew byte[len]; is.read(msgs); // for(int i0;ilen;i){ // msgs[i] (byte) is.read(); // } String msgnew String(msgs); System.out.println(收到msg); return msg; } catch (IOException e) { throw new RuntimeException(e); } } public void replyMsg(ClientUser client,String msg){ //转发消息 for(int i0;iSocketList.size();i){ ClientUser cuSocketList.get(i); Socket scu.socket; if (s!client.socket){ try { String m client.account说msg;//注意拼接逻辑 send(m,s.getOutputStream()); } catch (IOException e) { throw new RuntimeException(e); } } } } public void proClintMsg(Socket socket){ //注意循环速度太快导致cpu被占满io流根本没机会运行所以这里加一个println让cpu空闲下来 new Thread(()-{ //登录 //读取用户名 String UserNameproLogein(socket); ClientUser cunew ClientUser(UserName,socket); //保存ClientUser对象 SocketList.add(cu); while(true) { try { InputStream iscu.socket.getInputStream(); System.out.println(监听cu.socket.getPort()消息中);//顺序不对 String msgreceive(is); replyMsg(cu,msg); } catch (IOException e) { throw new RuntimeException(e); } } }).start(); } public String proLogein(Socket socket){ try { InputStream issocket.getInputStream(); int lenis.read(); byte[] msgsnew byte[len]; is.read(msgs); String userNamenew String(msgs); System.out.println(用户userName登录了); return userName; } catch (IOException e) { throw new RuntimeException(e); } } public static void main(String[] args) { Server servernew Server(); //初始化 server.init(); //匿名内部类放到线程中(监听连接部分) new Thread(()-{ while(true) { System.out.println(等待连接...); Socket s server.listen(); System.out.println(有新的连接s.getInetAddress()s.getPort()); server.proClintMsg(s);//处理客户端消息 每个客户端一个线程 } }).start(); } }

相关新闻

蓝桥杯算法竞赛:DFS与BFS搜索算法核心原理与真题实战

蓝桥杯算法竞赛:DFS与BFS搜索算法核心原理与真题实战

1. 搜索专题在蓝桥杯中的核心地位与备考价值如果你正在准备蓝桥杯,尤其是软件类(C/C、Java、Python组)的比赛,那么“搜索”这个专题,绝对是你绕不开、也绝不能轻视的核心高地。我参加过几届蓝桥杯的评审和辅导工作&…

2026/10/22 19:05:14 阅读更多 →
C#字符串长度全解析:码元、字符与字节长度的区别与应用

C#字符串长度全解析:码元、字符与字节长度的区别与应用

1. 从一次“字符截断”事故说起 那天下午,我正在调试一个处理多语言用户名的数据导出功能。逻辑很简单:从数据库读取用户信息,生成CSV文件。测试时一切正常,直到一个日本用户的名字“山田 太郎”出现在列表里。导出的文件在其他系…

2026/10/21 8:17:04 阅读更多 →
涂胶显影机(Track)各职级技术岗人才综合评估结论及录用判定标准

涂胶显影机(Track)各职级技术岗人才综合评估结论及录用判定标准

一、总则(终审核心逻辑) 本标准为Track技术招聘最终终审唯一依据,完全贯通公司整套Track招聘体系:各职级14维面试打分卡、两轮分层技术面试、HR分层分级面试、面试官权责体系、职级薪酬体系、法务竞业合规审核与竞业储备体系。 本制度固化三方评审权重,明确技术、HR、法…

2026/10/19 21:40:26 阅读更多 →

最新新闻

Electron桌面应用开发实战:从环境搭建到打包发布全流程

Electron桌面应用开发实战:从环境搭建到打包发布全流程

做前端这些年,我大部分时间都在跟浏览器标签页打交道,直到第一次把桌面应用跑起来,才发现原来自己一直被限制在地址栏和刷新按钮围起来的框框里。Electron这个词,最开始是在某段时间频繁出现在同事的讨论里,一个用HTML…

2026/10/22 10:18:38 阅读更多 →
滑盖智能锁T109深度解析:结构原理、安装调试与故障排查

滑盖智能锁T109深度解析:结构原理、安装调试与故障排查

简介:亚太天能T109滑盖智能锁产品说明书是一份PDF格式的官方技术文档,主要面向智能锁安装人员、终端用户及售后维护者,帮助快速掌握产品安装、配置与常见故障处理。全包仅1个PDF文件,大小4.37MB,内容结构清晰&#xff…

2026/10/22 11:01:53 阅读更多 →
PMSM弱磁控制原理与Simulink建模:高速AGV驱动系统设计指南

PMSM弱磁控制原理与Simulink建模:高速AGV驱动系统设计指南

上个月我在调试一台高速AGV的驱动系统,整车要求空载跑到8m/s,电机转速已经拉到额定点,驱动器的输出电压也顶到了母线电压极限附近。再往上踩速度指令,转速纹丝不动,三相电流反而开始震荡。那会儿我的第一反应就是&…

2026/10/22 9:44:47 阅读更多 →
C++核心知识点:从内存管理到STL的实战指南

C++核心知识点:从内存管理到STL的实战指南

C 这门语言我前前后后折腾了十几年,用它写过嵌入式驱动、做过游戏服务端,也搭过基础组件库。每次看到新人一头扎进"C 核心知识点"这个搜索词,我其实挺感慨的——这门语言的难点从来不是语法多,而是知识点之间的耦合太深…

2026/10/22 10:42:00 阅读更多 →
T109滑盖智能锁怎么装?安装调试与故障排查全攻略

T109滑盖智能锁怎么装?安装调试与故障排查全攻略

简介:亚太天能T109滑盖智能锁产品说明书以PDF格式发布,适合智能锁用户、安装人员与售后维修人员阅读。内容围绕T109系列指纹密码刷卡锁展开,先介绍前面板、后面板、锁体、机械钥匙、电池盒盖等部件名称与功能,再给出完整安装步骤&…

2026/10/22 10:40:08 阅读更多 →
LLM知识降熵:从信息垄断到理解权下放

LLM知识降熵:从信息垄断到理解权下放

你有没有过这种经历:翻开源码注释、论文摘要或者一份专业报告,每个字都认识,连在一起却像天书。想找人聊聊,身边要么没人懂,要么懂的懒得跟你解释。后来我试着把同一段内容丢给一个大语言模型,几秒钟之后&a…

2026/10/22 10:56:37 阅读更多 →

日新闻

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/22 1:47:45 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/21 21:32:28 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/22 5:12:39 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/21 21:50:56 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/21 21:51:55 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/22 19:06:46 阅读更多 →