实现服务器和客户端数据交互,Java Socket有妙招
摘要:在Java SDK中,对于Socket原生提供了支持,它分为ServerSocket和Socket。
本文分享自华为云社区《Java Socket 如何实现服务器和客户端数据交互》,作者: jackwangcumt 。
1 Socket概述
根据百度百科的定义,Socket 译为套接字,它是对网络中不同主机上的应用进程之间进行双向通信的端点的抽象。一个Socket实例就是网络上进程通信的一端,提供了应用层进程利用网络协议交换数据的机制。Socket向上连接各种应用进程,向下连接各种网络协议,是应用程序通过网络协议进行通信的接口。其示意图如下下图所示:
(来自《Java TCP/IP Socket编程》)
从上图可知,套接字Socket在OSI七层模型中处于应用层和传输层之间,是一个重要的接口。一般来说,传输层协议有TCP协议和UDP协议。这两个协议底层都基于IP网络层协议。
2 Java Socket 实现
在Java SDK中,对于Socket原生提供了支持,它分为ServerSocket和Socket,其中ServerSocket发起一个服务端的Socket,其中需要提供一个端口号,如果给定0,则自动申请可用的端口。当然了,也可以指定具体的端口号(有一定的范围,不超过 65535 )。不过这里需要注意,传入的端口不能被其他应用占用,否则启动服务失败。下面给出一个简单的ServerSocket示例,代码如下:
package com.example.demo.network;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class MyServer {
//<= 65535
private static final int PORT = 65535; public static void main(String[] args) throws Exception { try (ServerSocket listener = new ServerSocket(PORT)) {
System.out.println("Server Started");
//线程池大小,它根据客户端数来决定,当大于10时,则之前的10个线程仍然可以工作,
// 而超过的线程则进入队列中,等待。
//当之前的客户端释放量后,则在队列中的线程仍然可以工作。
ExecutorService pool = Executors.newFixedThreadPool(10);
while (true) {
//多线程
pool.execute(new MyServerDemo01(listener.accept()));
System.out.println(pool);
}
}
}
//Runnable接口的实现对象可以被线程Thread调用
private static class MyServerDemo01 implements Runnable { private Socket socket; MyServerDemo01(Socket socket) {
this.socket = socket;
} @Override
public void run() {
System.out.println("Client [" + socket.getRemoteSocketAddress().toString()+" ] Connected");
try {
//输入
Scanner in = new Scanner(socket.getInputStream());
//输出
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
while (in.hasNextLine()) {
String msg = in.nextLine();
System.out.println("Client [" + socket.getRemoteSocketAddress().toString()+" ] : " + msg);
out.println(msg.toUpperCase());
}
} catch (Exception e) {
System.out.println("Error:" + socket+ e.getMessage());
} finally {
try {
//关闭socket
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("Closed: " + socket);
}
}
}
}
启动该Server端,并开始监听客户端的连接。当客户端没有连接时,服务器线程池pool并未启动单独的线程。下面给出客户端的Java Socket实现,具体的示例代码如下:
package com.example.demo.network;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;
public class MyClient {
//<= 65535
private static final int PORT = 65535;
//服务器地址
private static final String IP = "127.0.0.1"; public static void main(String[] args) throws Exception { try (Socket socket = new Socket(IP, PORT)) {
System.out.println("Client ["+socket.getRemoteSocketAddress().toString()+" ] Started");
Scanner scanner = new Scanner(System.in);
Scanner in = new Scanner(socket.getInputStream());
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
while (scanner.hasNextLine()) {
out.println(scanner.nextLine());
System.out.println("Server Response:"+ in.nextLine());
}
}catch (Exception ex){
System.out.println("Error : "+ ex.getMessage());
}
}
}
从代码可知,try (Socket socket = new Socket(IP, PORT)) 是一种包含资源释放的try-with-resource机制,它会自动进行资源释放,而不需要手动进行释放。Socket对象要想和服务器通信,必须要明确服务器的IP地址和端口,否则不能正确通信,Socket启动时,也会在主机上占用自己的端口。我们首先启动Server端,然后可以同时启动10个以上的Client端,比如13个,那么超过Executors.newFixedThreadPool(10)限定的数量10后,将进入queued tasks队列中进行排队等待。通过打印pool对象,可以看出当前的状态,比如[Running, pool size = 4, active threads = 4, queued tasks = 0, completed tasks = 0]说明当前在运行状态,线程池大小为10,激活的线程为10,等待的任务线程queued tasks为0。
下面给出Server端相关输出示例:
Server Started
java.util.concurrent.ThreadPoolExecutor@256216b3[Running, pool size = 1, active threads = 1, queued tasks = 0, completed tasks = 0]
Client [/127.0.0.1:64590 ] Connected
java.util.concurrent.ThreadPoolExecutor@256216b3[Running, pool size = 2, active threads = 2, queued tasks = 0, completed tasks = 0]
Client [/127.0.0.1:64597 ] Connected
java.util.concurrent.ThreadPoolExecutor@256216b3[Running, pool size = 3, active threads = 3, queued tasks = 0, completed tasks = 0]
Client [/127.0.0.1:64603 ] Connected
Client [/127.0.0.1:64590 ] : hello
Client [/127.0.0.1:64590 ] : hello
Client [/127.0.0.1:64597 ] : world
Client [/127.0.0.1:64597 ] : world
Client [/127.0.0.1:64603 ] : python
Client [/127.0.0.1:64597 ] : python02
java.util.concurrent.ThreadPoolExecutor@256216b3[Running, pool size = 4, active threads = 4, queued tasks = 0, completed tasks = 0]
Client [/127.0.0.1:57806 ] Connected
java.util.concurrent.ThreadPoolExecutor@256216b3[Running, pool size = 5, active threads = 5, queued tasks = 0, completed tasks = 0]
Client [/127.0.0.1:57814 ] Connected
java.util.concurrent.ThreadPoolExecutor@256216b3[Running, pool size = 6, active threads = 6, queued tasks = 0, completed tasks = 0]
Client [/127.0.0.1:57820 ] Connected
java.util.concurrent.ThreadPoolExecutor@256216b3[Running, pool size = 7, active threads = 7, queued tasks = 0, completed tasks = 0]
Client [/127.0.0.1:57827 ] Connected
java.util.concurrent.ThreadPoolExecutor@256216b3[Running, pool size = 8, active threads = 8, queued tasks = 0, completed tasks = 0]
Client [/127.0.0.1:57833 ] Connected
java.util.concurrent.ThreadPoolExecutor@256216b3[Running, pool size = 9, active threads = 9, queued tasks = 0, completed tasks = 0]
Client [/127.0.0.1:57839 ] Connected
java.util.concurrent.ThreadPoolExecutor@256216b3[Running, pool size = 10, active threads = 10, queued tasks = 0, completed tasks = 0]
Client [/127.0.0.1:57845 ] Connected
java.util.concurrent.ThreadPoolExecutor@256216b3[Running, pool size = 10, active threads = 10, queued tasks = 1, completed tasks = 0]
java.util.concurrent.ThreadPoolExecutor@256216b3[Running, pool size = 10, active threads = 10, queued tasks = 2, completed tasks = 0]
java.util.concurrent.ThreadPoolExecutor@256216b3[Running, pool size = 10, active threads = 10, queued tasks = 3, completed tasks = 0]
Closed: Socket[addr=/127.0.0.1,port=64590,localport=65535]
Client [/127.0.0.1:57854 ] Connected
Client [/127.0.0.1:57814 ] : t2
Client [/127.0.0.1:57814 ] : tw2
客户端相关输入输出界面如下:
Client [/127.0.0.1:65535 ] Started
world
Server Response:WORLD
world
Server Response:WORLD
python02
Server Response:PYTHON02
实现服务器和客户端数据交互,Java Socket有妙招的更多相关文章
- 服务器与客户端数据交互 (json)
服务器返回到客户端json对象,是什么类型,而用ajax处理后,变成什么了. > 猜测1:服务器返回的数据带双引号: "返回值",理由:因为返回的类型都是字符串. 结果无 ...
- 服务器和客户端的交互方式(Socket,http协议)和各自特点适用范围
1 数据传输方式 1.1 Socket传输的定义和其特点 所谓socket通常也称作"套接字",实现服务器和客户端之间的物理连接,并进行数据传输,主要有UDP和TCP两个协议.S ...
- 基于asp.net MVC 的服务器和客户端的交互(一)
架构思想 三层架构 提出了一种基于ASP.NET开发方式的三层架构的Web应用系统构造思想.其基本内容是:将面向对象的UML建模与Web应用系统开发 相结合,将整个系统分成适合ASP.NET开发方式的 ...
- Linux系统编程(34)—— socket编程之TCP服务器与客户端的交互
前面几篇中实现的client每次运行只能从命令行读取一个字符串发给服务器,再从服务器收回来,现在我们把它改成交互式的,不断从终端接受用户输入并和server交互. /* client.c */ #in ...
- Socket实现服务器与客户端的交互
连接过程: 根据连接启动的方式以及本地套接字要连接的目标,套接字之间的连接过程可以分为三个步骤:服务器监听,客户端请求,连接确认. (1)服务器监听:是服务器端套接字并不定位具体的客户端套接 ...
- 基于asp.net MVC 的服务器和客户端的交互(三)之客户端请求响应
一.分析 WEB API 中HTTP 请求方式的四个主要方法 (GET, PUT, POST, DELETE), 按照下列方式映射为 CURD 操作: GET 用于获取 URI 资源的进行展示,GET ...
- Raknet实现的简单服务器与客户端的交互
1. 首先下载Raknet的源代码,我用的是4.0的,不是最新的,解压后编译DLL工程,编译完成后进入解压的根目录下,进入Lib文件夹下找到RakNet_DLL_Debug_Win32.dll, R ...
- 基于asp.net MVC 的服务器和客户端的交互(二)之获取Oauth 2.0认证权限
基本Web API的ASP.NET的Oauth2认证 增加Token额外字段 增加Scope授权字段 持久化Token 设计Token的时间间隔 刷新Token后失效老的Token 自定义验证[重启I ...
- 一个 Java 的 Socket 服务器和客户端通信的例子
一个 HelloWord 级别的 Java Socket 通信的例子.通讯过程: 先启动 Server 端,进入一个死循环以便一直监听某端口是否有连接请求.然后运行 Client 端,客户端发出连接请 ...
随机推荐
- JVM详解(一)——概述
Test https://www.cnblogs.com/yrxing/p/14651346.html#gc的基础知识 https://www.cnblogs.com/yinzhengjie/p/92 ...
- Django的form组件基本使用——生成标签
from django.contrib import admin from django.urls import path from app01 import views urlpatterns = ...
- 安全测试工具(1)- Burp Suite Pro的安装教程
啥是Burp Suite 用于攻击web 应用程序的集成平台 程序员必备技能,不仅可以拿来做渗透测试.漏洞挖掘还能帮助程序员调试程序 Bug 它包含了许多Burp工具,这些不同的burp工具通过协同工 ...
- open failed: EACCES (Permission denied)
出现背景:调用系统相册进行图片展示,但是没有成功,是空白的,且检查权限无问题 解决方法
- 【死磕NIO】— 阻塞、非阻塞、同步、异步,傻傻分不清楚
万事从最基本的开始. 要想完全掌握 NIO,并不是掌握上面文章([死磕NIO]- NIO基础详解)中的三大组件就可以了,我们还需要掌握一些基本概念,如什么是 IO,5 种IO模型的区别,什么是阻塞&a ...
- ecshop调用指定广告的方法
在include/lib_goods.php文件下面新增:function getads($cat,$num){ $time = gmtime();$sql = "SELECT * FROM ...
- FastAPI logger日志记录方案 loguru模块
实现方式: 采用 loguru 模块.跟flask直接挂载到app上有区别,当然也可以尝试去这样做. 但是 好像没有这个必要.要的就是个快速.整那些子虚乌有的东西完全木有意义. 1.首先是去项目git ...
- 没想到 TCP 协议,还有这样的骚操作。。。
大家好,我是小林. 昨晚有位读者问了我这么个问题: 大概意思是,一个已经建立的 TCP 连接,客户端中途宕机了,而服务端此时也没有数据要发送,一直处于 establish 状态,客户端恢复后,向服务端 ...
- Expression Tree 遍历集合
场景 从接口返回的数据是集合,却是 object 类型的.这个时候需要遍历这个集合.现提供两种方法. 方法一: 因为集合是可枚举的,所以可以尝试转为 IEnumerable 类型,然后遍历即可. st ...
- pkusc2021游记
@ 目录 前言 Day 0 Day 1 Day 2 Day 3 前言 到时候APIO的大概也会写在这篇里吧. Day 0 车,公交,飞机,公交,车 坐了半天的交通终于到了,整个人都坐的晕乎乎的,然后看 ...