热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

javasocket调试_JAVA实现SOCKET多客户端通信的案例

一、ServerSocket1.为了方便调试,先创建一个界面用于显示客户端连接信息基于javafx包写的一个简单界面!javafx.scene.cont

一、ServerSocket

1.为了方便调试,先创建一个界面用于显示客户端连接信息

cf4ecb60aa85ada2860d7f615e65dba9.png

基于javafx包写的一个简单界面!

javafx.scene.control.TextArea ta = new javafx.scene.control.TextArea();

@Override

public void start(Stage primaryStage) throws Exception {

scene = new Scene(ta,450,200);

primaryStage.setTitle("SocketServer");

primaryStage.setScene(scene);

primaryStage.show();

pStage = primaryStage;

new Thread(new MyServer()).start(); //创建线程启动Socket服务

}

2.启动Socket服务

public class MyServer implements Runnable{

@Override

public void run() {

try{

java.net.ServerSocket serverSocket = new java.net.ServerSocket(8000);

ta.appendText("Server started at " + new Date()+"\n");

while(true){

Socket socket = serverSocket.accept(); //程序会在这里阻塞,直到等到客户端连接

clientNumber++;

/*

这里就是在界面中输出一些服务器、和连接的客户端信息

*/

Platform.runLater(()->{

ta.appendText("Starting thread for client " + clientNumber + " at " +

new Date() +"\n");

InetAddress inetAddress = socket.getInetAddress();

ta.appendText("Client "+clientNumber + "'s host name is" +inetAddress.getHostName()

+"\n");

ta.appendText("Client"+clientNumber + "'s IP address is "+ inetAddress.getHostAddress()+"\n");

});

/*

每有一个客户端连接服务器就创建一个线程,进行通信处理

*/

new Thread(new HandleServer(socket)).start();

try{

Thread.sleep(100); //多个客户端连续快速连接服务器时,可能出现问题,这里设置延时

}catch (InterruptedException e){

e.printStackTrace();

}

}

}catch (IOException e){

e.printStackTrace();

}

}

}

这一段代码主要作用就是循环等待客户端连接服务器:

Socket socket = serverSocket.accept();

在写这篇博客时,突然想知道阻塞的原理就去查了一下。。。。

然而并没有看懂。。这个应该涉及到操作系统层面,等之后把操作系统搞明白了在来补充吧。

3.服务器处理类HandleServer

class HandleServer implements Runnable {

private Socket socket;

private int name;

private int toClientID;

private DataOutputStream outputStream;

private DataInputStream inputStream;

public HandleServer(Socket socket){

this.socket = socket;

ServerTools.Tools().add(this);

this.name = clientNumber;

}

@Override

public void run() {

try{

inputStream = new DataInputStream(socket.getInputStream());

outputStream = new DataOutputStream(socket.getOutputStream());

outputStream.writeUTF("Your ID is:"+clientNumber);

while (true){

toClientID = inputStream.readInt();

String messageGET = inputStream.readUTF();

int err = ServerTools.Tools().MyWriteUTF(messageGET,toClientID); //MyWriteUTF 是一个自定义方法,serverTools.Tools()是一个工具类,一个静态对象。

if (err==0){

outputStream.writeUTF("No have this ID!");

}

Platform.runLater(()->{

ta.appendText(socket.getInetAddress().getHostName()+" Message received from client:" + messageGET +"\n" );

});

System.out.println(clientNumber);

}

}catch (IOException e){

clientNumber--;

System.out.println(clientNumber);

System.err.println("Client is closed!");

}

}

这一块的代码主要就是创建输入输出数据流了

inputStream = new DataInputStream(socket.getInputStream());

outputStream = new DataOutputStream(socket.getOutputStream());

4.一些方法方便ServerTools类实现

public void MyWriteUTF(String message){

try {

outputStream.writeUTF(message);

} catch (IOException e) {

ServerTools.Tools().remove(this);

e.printStackTrace();

}

}

public int getName() {

return name;

}

二、ServerTools

1.实现指定服务器ID输出信息的工具

public class ServerTools {

private static final ServerTools servertools = new ServerTools();

public static ServerTools Tools(){

return servertools;

}

Vector vector = new Vector();

public void add(MyServerSocket.HandleServer cs){

vector.add(cs);

}

public void remove(MyServerSocket.HandleServer cs){

vector.remove(cs);

}

public int MyWriteUTF(String message,int target) {

for (int i &#61; 0; i <&#61; target; i&#43;&#43;){

try {

if (vector.get(i).getName() &#61;&#61; target) {

MyServerSocket.HandleServer MSSHC &#61; vector.get(i);

MSSHC.MyWriteUTF(message);

return 1;

}

}catch (ArrayIndexOutOfBoundsException e){

e.printStackTrace();

return 0;

}

}

return 0;

}

}

vector用于保存客户端连接信息

一个粗糙的处理方式&#xff0c;逻辑上缺陷还很严重&#xff0c;主要我好像没找到这样的框架&#xff1f;&#xff1f;&#xff1f;

缺陷&#xff1a;因为服务器要返回客户端的ID让客户端将ID显示到交互界面&#xff0c;所以存在情况客户端多次连接断开后会使返回的ID出现重复

三、ClientSocket

1.同样的先建一个简单的界面用于输出信息和显示信息

e537c10e35c446b0f13d066442d9408e.png

第一个编辑框就是 输入要发送指定客户端的ID 例如&#xff1a;1 或 2 这样的&#xff1f;&#xff1f;&#xff1f;

第二个编辑框就是 输入你要发送的信息了&#xff0c;很清楚

下面的就是显示框&#xff0c;嗯&#xff01;

public class MyClientSocket extends Application {

private Socket socket;

private DataOutputStream toServer &#61; null;

private DataInputStream fromServer &#61; null;

private String ID;

private int targetID &#61; 0;

private TextArea ta;

&#64;Override

public void start(Stage primaryStage) throws Exception {

BorderPane paneForTextField &#61; new BorderPane();

paneForTextField.setPadding(new Insets(5,5,5,5));

paneForTextField.setStyle("-fx-border-color: green");

paneForTextField.setLeft(new Label("Enter a Message:"));

TextField tf &#61; new TextField();

tf.setAlignment(Pos.BOTTOM_RIGHT);

paneForTextField.setCenter(tf);

BorderPane ID_lable &#61; new BorderPane();

ID_lable.setPadding(new Insets(5,5,5,5));

ID_lable.setStyle("-fx-border-color: green");

ID_lable.setLeft(new Label("Enter a ID for send message:"));

TextField getId &#61; new TextField();

getId.setAlignment(Pos.BOTTOM_RIGHT);

ID_lable.setCenter(getId);

paneForTextField.setTop(ID_lable);

BorderPane mainPane &#61; new BorderPane();

ta &#61; new TextArea();

mainPane.setCenter(new ScrollPane(ta));

mainPane.setTop(paneForTextField);

Scene scene &#61; new Scene(mainPane,450,200);

primaryStage.setTitle("SocketClient");

primaryStage.setScene(scene);

primaryStage.show();

tf.setOnAction(new EventHandler() {

&#64;Override

public void handle(ActionEvent event) {

targetID &#61; Integer.parseInt(getId.getText().trim());

if (targetID > 0 || targetID!&#61;Integer.parseInt(ID));

else return;

try {

String putMessage &#61; tf.getText().trim();

toServer.writeInt(targetID);

toServer.writeUTF(putMessage);

toServer.flush();

ta.appendText("PUT message is :"&#43; putMessage &#43;"\n");

tf.setText("");

}catch (IOException ex ){

System.err.println(ex);

}

}

});

try{

socket &#61; new Socket("localhost",8000);

fromServer &#61; new DataInputStream(socket.getInputStream());

toServer &#61; new DataOutputStream(socket.getOutputStream());

ID &#61; fromServer.readUTF();

paneForTextField.setRight(new Label("Your ID is:"&#43;ID));

new Thread(new getMessage(socket,fromServer)).start();

}catch (IOException ex){

ta.appendText(ex.toString() &#43;"\n");

}

}

}

一样的要new一个Socket 去连接服务器&#xff0c;socket()&#xff0c;括号里的就是服务器的IP&#xff0c;和程序的端口号了&#xff0c;这种基于tcp协议的好像都是一个样&#xff1f;&#xff1f;&#xff1f;

2.创建一个线程用于循环获取信息并显示

class getMessage implements Runnable{

private Socket socket;

private DataInputStream formServer;

public getMessage(Socket socket,DataInputStream formServer){

this.socket &#61; socket;

this.formServer &#61; formServer;

}

&#64;Override

public void run() {

try {

while (true) {

String Message &#61; formServer.readUTF();

try{

Thread.sleep(100);

}catch (InterruptedException e) {

e.printStackTrace();

}

ta.appendText("GET message from server is:" &#43; Message &#43; "\n");

}

}catch (IOException e){

System.err.println(e);

}

}

}

很简单了&#xff0c;依旧是输入输出数据流&#xff0c;然后循环等待信息并输出。

3.新建一个TestClient类 这个类 和ClientSocket 一模一样 就是拿来测试的

95919d302f463131d82713f9b6f7057e.png

四、总结

java写socket 是真的简单&#xff01;&#xff01;&#xff01;^_ ^!

f471a2b2ce975c005ac5b4a41349061a.png

以上这篇JAVA实现SOCKET多客户端通信的案例就是小编分享给大家的全部内容了&#xff0c;希望能给大家一个参考&#xff0c;也希望大家多多支持脚本之家。



推荐阅读
  • Java学习笔记之面向对象编程(OOP)
    本文介绍了Java学习笔记中的面向对象编程(OOP)内容,包括OOP的三大特性(封装、继承、多态)和五大原则(单一职责原则、开放封闭原则、里式替换原则、依赖倒置原则)。通过学习OOP,可以提高代码复用性、拓展性和安全性。 ... [详细]
  • 前景:当UI一个查询条件为多项选择,或录入多个条件的时候,比如查询所有名称里面包含以下动态条件,需要模糊查询里面每一项时比如是这样一个数组条件:newstring[]{兴业银行, ... [详细]
  • 本文介绍了iOS数据库Sqlite的SQL语句分类和常见约束关键字。SQL语句分为DDL、DML和DQL三种类型,其中DDL语句用于定义、删除和修改数据表,关键字包括create、drop和alter。常见约束关键字包括if not exists、if exists、primary key、autoincrement、not null和default。此外,还介绍了常见的数据库数据类型,包括integer、text和real。 ... [详细]
  • 本文详细介绍了如何使用MySQL来显示SQL语句的执行时间,并通过MySQL Query Profiler获取CPU和内存使用量以及系统锁和表锁的时间。同时介绍了效能分析的三种方法:瓶颈分析、工作负载分析和基于比率的分析。 ... [详细]
  • Ihavethefollowingonhtml我在html上有以下内容<html><head><scriptsrc..3003_Tes ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 在Android开发中,使用Picasso库可以实现对网络图片的等比例缩放。本文介绍了使用Picasso库进行图片缩放的方法,并提供了具体的代码实现。通过获取图片的宽高,计算目标宽度和高度,并创建新图实现等比例缩放。 ... [详细]
  • 本文介绍了在rhel5.5操作系统下搭建网关+LAMP+postfix+dhcp的步骤和配置方法。通过配置dhcp自动分配ip、实现外网访问公司网站、内网收发邮件、内网上网以及SNAT转换等功能。详细介绍了安装dhcp和配置相关文件的步骤,并提供了相关的命令和配置示例。 ... [详细]
  • 本文分享了一个关于在C#中使用异步代码的问题,作者在控制台中运行时代码正常工作,但在Windows窗体中却无法正常工作。作者尝试搜索局域网上的主机,但在窗体中计数器没有减少。文章提供了相关的代码和解决思路。 ... [详细]
  • Linux重启网络命令实例及关机和重启示例教程
    本文介绍了Linux系统中重启网络命令的实例,以及使用不同方式关机和重启系统的示例教程。包括使用图形界面和控制台访问系统的方法,以及使用shutdown命令进行系统关机和重启的句法和用法。 ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • 本文介绍了九度OnlineJudge中的1002题目“Grading”的解决方法。该题目要求设计一个公平的评分过程,将每个考题分配给3个独立的专家,如果他们的评分不一致,则需要请一位裁判做出最终决定。文章详细描述了评分规则,并给出了解决该问题的程序。 ... [详细]
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • 深入理解CSS中的margin属性及其应用场景
    本文主要介绍了CSS中的margin属性及其应用场景,包括垂直外边距合并、padding的使用时机、行内替换元素与费替换元素的区别、margin的基线、盒子的物理大小、显示大小、逻辑大小等知识点。通过深入理解这些概念,读者可以更好地掌握margin的用法和原理。同时,文中提供了一些相关的文档和规范供读者参考。 ... [详细]
author-avatar
吴尧丹_449
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有