当前位置: 首页 > Web前端 > JavaScript

实现服务端和客户端的数据交互,JavaSocket有妙招

时间:2023-03-27 00:03:25 JavaScript

本文分享自华为云社区《Java Socket 如何实现服务器和客户端数据交互》,作者:jackwangcumt。GoodMai1Socket概述根据百度百科的定义,Socket翻译为套接字,是对网络中不同主机上的应用进程之间双向通信的端点的抽象。Socket实例是网络上进程通信的一端,为应用层进程使用网络协议交换数据提供了一种机制。Socket向上连接各种应用进程,向下连接各种网络协议,是应用程序通过网络协议进行通信的接口。其示意图如下图所示:(来自《Java TCP/IP Socket编程》)从上图可以看出,Socket是OSI七层模型中应用层和传输层之间的重要接口。一般来说,传输层协议包括TCP协议和UDP协议。这两个协议的底层都是基于IP网络层协议。2JavaSocket在JavaSDK中实现,提供了对Socket的原生支持。分为ServerSocket和Socket。ServerSocket发起服务端Socket,需要提供端口号。如果给出0,将自动请求可用端口。当然,你也可以指定一个特定的端口号(有一定的范围,不超过65535)。不过这里要注意,传入的端口不能被其他应用程序占用,否则会导致服务启动失败。下面给出一个简单的ServerSocket示例,代码如下:;importjava.util.Scanner;importjava.util.concurrent.ExecutorService;importjava.util.concurrent.Executors;publicclassMyServer{//<=65535privatestaticfinalintPORT=65535;publicstaticvoidmain(String[]args)throwsException{try(ServerSocketlistener=newServerSocket(PORT)){System.out.println("ServerStarted");//线程池大小,根据client数量决定,当大于10时,则前10个Thread仍可工作,//更多线程进入队列等待。//当上一个client释放金额时,队列中的线程仍然可以工作。ExecutorServicepool=Executors.newFixedThreadPool(10);while(true){//多线程pool.execute(newMyServerDemo01(listener.accept()));System.out.println(池);}}}//Runnable接口Thread可以调用实现对象privatestaticclassMyServerDemo01implementsRunnable{privateSocketsocket;MyServerDemo01(Socketsocket){this.socket=socket;}@Overridepublicvoidrun(){System.out.println("Client["+socket.getRemoteSocketAddress().toString()+"]Connected");try{//输入扫描器in=newScanner(socket.getInputStream());//输出PrintWriterout=newPrintWriter(socket.getOutputStream(),true);while(in.hasNextLine()){Stringmsg=in.nextLine();System.out.println("客户端["+socket.getRemoteSocketAddress().toString()+"]:"+msg);out.println(msg.toUpperCase());}}catch(Exceptione){System.out.println("错误:"+socket+e.getMessage());}finally{try{//关闭套接字socket.close();}catch(IOExceptione){e.printStackTrace();}System.out.println("关闭:"+socket);}}}}启动服务器,开始监听客户端的连接。当客户端未连接时,服务器线程池不会启动单独的线程。下面给出客户端的JavaSocket实现,具体示例代码如下:packagecom.example.demo.network;importjava.io.PrintWriter;importjava.net.Socket;importjava.util.Scanner;publicclassMyClient{//<=65535privatestaticfinalintPORT=65535;//服务器地址privatestaticfinalStringIP="127.0.0.1";publicstaticvoidmain(String[]args)throwsException{try(Socketsocket=newSocket(IP,PORT)){System.out.println("Client["+socket.getRemoteSocketAddress().toString()+"]开始");扫描仪扫描仪=新扫描仪(System.in);扫描仪in=newScanner(socket.getInputStream());PrintWriterout=newPrintWriter(socket.getOutputStream(),true);while(scanner.hasNextLine()){out.println(scanner.nextLine());System.out.println("服务器响应:"+in.nextLine());}}catch(Exceptionex){System.out.println("错误:"+ex.getMessage());}}}从代码中可以看出try(Socketsocket=newSocket(IP,PORT))是一种包含资源释放的try-with-resource机制,会自动释放资源,不需要手动释放Socket对象。与服务器进行通信,必须指定服务器的IP地址和端口,否则无法正确进行通信,并且Socket在启动时,也会在主机上占用自己的端口。我们先启动Server,然后可以同时启动10个以上的Client,比如13个,超过10个Executors.newFixedThreadPool(10)的限制后,就会进入queuedtasks队列排队等候。通过打印池对象,可以看到当前状态,如[Running,poolsize=4,activethreads=4,queuedtasks=0,completedtasks=0]表示当前运行状态,线程池大小为10,active线程为10,等待任务线程queuedtasks为0。下面给服务器端相关输出显示示例:ServerStartedjava.util.concurrent.ThreadPoolExecutor@256216b3[Running,poolsize=1,activethreads=1,queuedtasks=0,completedtasks=0]Client[/127.0.0.1:64590]Connectedjava.util.concurrent.ThreadPoolExecutor@256216b3[Running,poolsize=2,activethreads=2,queuedtasks=0,completedtasks=0]Client[/127.0.0.1:64597]Connectedjava.util.concurrent.ThreadPoolExecutor@256216b3[正在运行,池大小=3,活动线程=3,排队任务=0,已完成任务=0]客户端[/127.0.0.1:64603]ConnectedClient[/127.0.0.1:64590]:helloClient[/127.0.0.1:64590]:helloClient[/127.0.0.1:64597]:worldClient[/127.0.0.1:64597]:worldClient[/127.0.0.1:64603]:pythonClient[/127.0.0.1:64597]:python02java.util.concurrent.ThreadPoolExecutor@256216b3[Running,poolsize=4,activethreads=4,queuedtasks=0,completedtasks=0]Client[/127.0.0.1:57806]Connectedjava.util.concurrent.ThreadPoolExecutor@256216b3[运行宁,池大小=5,活动线程=5,排队任务=0,完成任务=0]客户端[/127.0.0.1:57814]Connectedjava.util.concurrent.ThreadPoolExecutor@256216b3[正在运行,池大小=6,活动线程=6,排队任务=0,已完成任务=0]客户端[/127.0.0.1:57820]Connectedjava.util.concurrent.ThreadPoolExecutor@256216b3[正在运行,池大小=7,活动线程=7,排队任务=0,已完成tasks=0]Client[/127.0.0.1:57827]Connectedjava.util.concurrent.ThreadPoolExecutor@256216b3[Running,poolsize=8,activethreads=8,queuedtasks=0,completedtasks=0]Client[/127.0.0.1:57833]Connectedjava.util.concurrent.ThreadPoolExecutor@256216b3[正在运行,池大小=9,活动线程=9,排队任务=0,完成任务=0]客户端[/127.0.0.1:57839]Connectedjava.util.concurrent.ThreadPoolExecutor@256216b3[Running,poolsize=10,activethreads=10,queuedtasks=0,completedtasks=0]Client[/127.0.0.1:57845]Connectedjava.util.concurrent.ThreadPoolExecutor@256216b3[运行,池大小=10,活动线程=10,排队任务=1,完成任务=0]java.util.concurrent.ThreadPoolExecutor@256216b3[运行,池大小=10,活动线程=10,排队任务=2,完成任务=0]java.util.concurrent.ThreadPoolExecutor@256216b3[正在运行,池大小=10,活动线程=10,排队任务=3,完成任务=0]关闭:套接字[地址=/127.0.0.1,port=64590,localport=65535]Client[/127.0.0.1:57854]ConnectedClient[/127.0.0.1:57814]:t2Client[/127.0.0.1:57814]:tw2client相关的输入输出接口如下:Client[/127.0.0.1:65535]StartedworldServerResponse:WORLDworldServerResponse:WORLDpython02ServerResponse:PYTHON02Haomai.comIT技术交易网站