当前位置: 首页 > news >正文

【JavaEE初阶系列】——网络编程 TCP客户端/服务器 程序实现

目录

🚩TCP流套接字编程

🍭ServerSocket API

🍭Socket API

🍭TCP服务器

🍭TCP客户端


🚩TCP流套接字编程

俩个关键的类 

  • ServerSocket (给服务器使用的类,使用这个类来绑定端口号)
  • Socket(既会给服务器用,又会给客户端用)

这俩个类都是用来表示socket文件的。(抽象了网卡这样的硬件设备)


🍭ServerSocket API

ServerSocket 是创建 TCP 服务端 Socket API
ServerSocket 构造方法:
方法签名方法说明
ServerSocket(int port)创建一个服务端流套接字Socket,并绑定到指定端口
ServerSocket 方法:
方法签名方法说明
Socket accept()开始监听指定端口(创建时绑定的端口),有客户端连接后,返回一个服务端Socket对象,并基于该Socket建立与客户端的连接,否则阻塞等待
void close()关闭此套接字

🍭Socket API

Socket 是客户端 Socket ,或服务端中接收到客户端建立连接( accept 方法)的请求后,返回的服务端Socket。
不管是客户端还是服务端 Socket ,都是双方建立连接以后,保存的对端信息,及用来与对方收发数据的。
Socket 构造方法:
方法签名方法说明
Socket(String host,int port)创建一个客户端流套接字Socket,并与对应IP的主机上,对应端口的进程连接。

Socket方法:

方法签名方法说明
InetAddress.getInetAddress()返回套接字所连接的地址
InputStream getInputStream()返回此套接字的输入流
OutputStream getOutputStream()返回此套接字的输出流

TCP是有连接的,连接就意味着通信双方会记录保存对端的信息,UDP来说,每次发送数据都得手动send方法中指定目标地址(UDP自身没有存储这个消息)TCP来说,则不需要,前提是需要先把连接给建立上。那么,如果建立连接呢?不需要代码干预,是系统内核自动负责完成的,对应app来说,客户端这边,主要是要发起”建立连接"动作,服务器这边,主要要把建立好的连接从内核中拿到app里。

我们看到大型商场里,都有很有海底捞,每天海底捞的人是非常多的,你要想去吃海底捞,就要排号。我们给海底捞店当作应用程序。而内核就是一个队列等待着去吃海底捞,每当有客人吃完,走了,空出了一桌,服务员就会叫号。

如果有客户端和服务器建立连接,这个时候服务器的应用程序是不需要任何操作(也没有任何感知的),内核直接完成了连接建立的流程(三次握手),完成流程之后,就会在内核的队列中(这个队列是每个serverSocket都有一个这样的队列)排队。

应用程序要想和客户端进行通信,就需要通过一个accept方法把内核队列里已经建立好的连接对象,拿到app中。


TCP中用ServerSocket (给服务器使用的类,使用这个类来绑定端口号),服务器启动之后用到accept方法,把内核中建立好的连接到应用程序中去(建立连接的过程是内核自动完成的,应用程序是捡漏的),如果没有与客户端连接,那么就阻塞等待。

  private ServerSocket serverSocket=null;public TCPEchoServer(int port) throws IOException {serverSocket =new ServerSocket(port);}public void start() throws IOException {System.out.println("服务器正式启动");while (true){//通过accpet方法,把内核中已经建立好的连接拿到app中//建立连接的细节流程都是内核自动完成的,app只需要“捡现成”的Socket clientSocket=serverSocket.accept();}}

在销售A卖楼盘的时候,销售在路上看到一个人想找一个人问问需不需要买房,然后那个男生就带去楼盘区,然后销售找了一个专业的置业顾问B,来介绍楼盘。而这个销售就去路上继续找人。

A:在外面招揽客人

B:给客人提供详细的服务

然后我们调用方法来处理当前的连接。首先我们先打印一个日志,表示已经与客户端建立连接了。

  • getPort() 和 getInetAddress() 得到对端的IP和端口 (客户端)
  • getLocalAddress() 和getLocalPort() 得到本地的IP和端口(服务器)
 //打印这个日志,来表示客户端连上了System.out.printf("[%s:%d] 客户端上线!\n",clientSocket.getInetAddress(),clientSocket.getPort());

  • 首先我们接收请求,用Scanner包装输入流,并读取请求。
  • 然后我们根据请求,计算响应
  • 最后把响应写回客户端 ,用PrintWriter类进行包装输出流,并flush().
 Scanner scanner=new Scanner(inputStream);//1.读取请求并解析,此处就以next来作为读取请求的方式,.next的规则是,读到“空白符”就返回String request=scanner.next();//2.根据请求,计算响应String response=process(request);
//3.把响应写回客户端//可以把String转成字节数组,写入到OutputStream,
//也可以使用PrintWriter把OutputStream包裹一下,来写入字符串PrintWriter printWriter=new PrintWriter(outputStream);
//此处的println不是打印到控制台了,而是写入到outputStream对应的流对象,也就是写入到clientSocket
//自然这个数据也就通过网络发送出去了,//此处使用println带有\n 也是为了后续 客户端这边 可以使用 scanner.next来读取数据printWriter.write(response);

空白符 是一类特殊的字符,换行,回车符,空格,制表符,翻页符,垂直制表符

后续客户端发起的请求,会以空白符作为结束标记(此处就约定使用\n)


🍭TCP服务器

package TCP;import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;public class TCPEchoServer {private ServerSocket serverSocket=null;public TCPEchoServer(int port) throws IOException {serverSocket =new ServerSocket(port);}public void start() throws IOException {System.out.println("服务器正式启动");while (true){//通过accpet方法,把内核中已经建立好的连接拿到app中//建立连接的细节流程都是内核自动完成的,app只需要“捡现成”的Socket clientSocket=serverSocket.accept();Thread t=new Thread(()->{processConnection(clientSocket);});t.start();}}//通过这个方法,来处理当前的连接public void processConnection(Socket clientSocket) {//打印这个日志,来表示客户端连上了System.out.printf("[%s:%d] 客户端上线!\n",clientSocket.getInetAddress(),clientSocket.getPort());try(InputStream inputStream=clientSocket.getInputStream();OutputStream outputStream=clientSocket.getOutputStream()) {//使用try()方式,避免后续用完了流对象,忘记关闭//由于客户端发来的数据,可能是"多条数据“,针对多条数据,就循环处理while (true){Scanner scanner=new Scanner(inputStream);if(!scanner.hasNext()){//连接断开了,此时循环就应该结束System.out.printf("[%s:%d] 客户端下线!\n",clientSocket.getInetAddress(),clientSocket.getPort());break;}//1.读取请求并解析,此处就以next来作为读取请求的方式,.next的规则是,读到“空白符”就返回String request=scanner.next();//2.根据请求,计算响应String response=process(request);//3.把响应写回客户端//可以把String转成字节数组,写入到OutputStream,//也可以使用PrintWriter把OutputStream包裹一下,来写入字符串PrintWriter printWriter=new PrintWriter(outputStream);//此处的println不是打印到控制台了,而是写入到outputStream对应的流对象,也就是写入到clientSocket//自然这个数据也就通过网络发送出去了,//此处使用println带有\n 也是为了后续 客户端这边 可以使用 scanner.next来读取数据printWriter.println(response);//此处还要记得有个操作,刷新缓冲区,如果没有刷新操作,可能数据仍然是在内存中,没有被写入网卡printWriter.flush();//打印了这次请求交互过程的内容System.out.printf("[%s:%d] req=%s resp=%s\n",clientSocket.getInetAddress(),clientSocket.getPort(),request,response);}} catch (IOException e) {throw new RuntimeException(e);}finally {//进行clientSocket的关闭try {clientSocket.close();} catch (IOException e) {throw new RuntimeException(e);}}}public String process(String request){return request;}public static void main(String[] args) throws IOException {TCPEchoServer tcpEchoServer=new TCPEchoServer(9090);tcpEchoServer.start();}
}

如果我们出现了多个客户端连接同一个服务器该怎么办呢?这就考虑到多线程的知识了,如果有客户端就开启线程。


🍭TCP客户端

  private Socket socket=null;public TCPClient(String serverIP, int serverPort) throws IOException {//需要在创建Socket的同时,和服务器”建立连接“ 此时就得告诉Socket服务器在哪里//具体建立连接的细节,不需要咱们代码手动干预,是内核自动负责的//当我们new这个对象的时候,操作系统内核,就开始使用 三次握手 具体细节 完成建立连接的过程socket =new Socket(serverIP,serverPort);}

TCP是连接的,我们需要对端的IP和端口号。所以我们要构造服务器的IP和端口号。

客户端是发出请求,并接收服务器返回的响应。

  • 我们先输入,并判断是否有输入,如果有输入就返回字符串。
  • 发出请求,就是用PrintWriter类来封装输出流,并flush()。
  • 然后接收服务器返回的响应,用Scanner来封装输入流。然后调用next()方法返回String字符串
  • 然后打印处理。
package TCP;import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;public class TCPClient {private Socket socket=null;public TCPClient(String serverIP, int serverPort) throws IOException {//需要在创建Socket的同时,和服务器”建立连接“ 此时就得告诉Socket服务器在哪里//具体建立连接的细节,不需要咱们代码手动干预,是内核自动负责的//当我们new这个对象的时候,操作系统内核,就开始使用 三次握手 具体细节 完成建立连接的过程socket =new Socket(serverIP,serverPort);}public void start(){System.out.println("客户端启动");//tcp客户端行为和udp客户端差不多//从服务器读取响应//把响应显示到界面上Scanner scanner=new Scanner(System.in);try(InputStream inputStream=socket.getInputStream();OutputStream outputStream=socket.getOutputStream()) {Scanner scanner1=new Scanner(inputStream);while (true){//1.从控制台输入内容System.out.println("->");String request=scanner.next();//2.把字符串作为请求,发送给服务器PrintWriter printWriter=new PrintWriter(outputStream);printWriter.println(request);printWriter.flush();//3.读取服务器返回的响应String response=scanner1.next();//4.界面显式内容System.out.println(response);}} catch (IOException e) {throw new RuntimeException(e);}}public static void main(String[] args) throws IOException {TCPClient tcpClient=new TCPClient("172.20.10.2",9090);tcpClient.start();}
}

你跑的快,耳边全是风声。

相关文章:

【JavaEE初阶系列】——网络编程 TCP客户端/服务器 程序实现

目录 🚩TCP流套接字编程 🍭ServerSocket API 🍭Socket API 🍭TCP服务器 🍭TCP客户端 🚩TCP流套接字编程 俩个关键的类 ServerSocket (给服务器使用的类,使用这个类来绑定端口号&#xff0…...

CMake构建OpenCv并导入QT项目过程中出现的问题汇总

前言 再此之前请确保你的环境变量是否配置,这是总共需要配置的环境变量 E:\cmake\bin E:\OpenCv\opencv\build\x64\vc15\bin F:\Qt\Tools\mingw730_64\bin F:\Qt\5.12.4\mingw73_64\bin 问题一: CMake Error: CMake was unable to find a build program…...

AcWing 796. 子矩阵的和——算法基础课题解

AcWing 796. 子矩阵的和 题目描述 输入一个 n 行 m 列的整数矩阵,再输入 q 个询问,每个询问包含四个整数 x1,y1,x2,y2,表示一个子矩阵的左上角坐标和右下角坐标。 对于每个询问输出子矩阵中所有数的和。 输入格式 第一行包含三个整数 n&…...

macos 查看 远程服务器是否开放某个端口

想要使用mac查看远程服务器某个端口是否开发&#xff0c;可通过 nc 命令&#xff0c;如下&#xff1a; nc -zv <服务器IP> <端口号>如果该端口开发&#xff0c;结果为&#xff1a;succeeded! Connection to <服务器IP> port <端口号> [类型] succeed…...

GraphQL注入

GraphQL概述 GraphQL是一种查询语言&#xff0c;用于API设计和数据交互&#xff0c;不仅仅用于查询数据库。GraphQL 允许客户端在一个请求中明确地指定需要的数据&#xff0c;并返回预期的结果&#xff1b;并且将数据查询和数据修改分离开&#xff0c;大大增加灵活性。GraphQL…...

以太坊源码阅读01

正所谓区块链&#xff0c;怎能不熟悉区块的数据结构呢&#xff1f;区块的结构体被保存在core/types/block.go文件中&#xff0c;下面是我截取出来的&#xff1a; type Block struct {header *Headeruncles []*Headertransactions Transactionswithdrawals Withdr…...

Spark-Scala语言实战(15)

在之前的文章中&#xff0c;我们学习了如何在spark中使用键值对中的学习键值对方法中的lookup&#xff0c;cogroup两种方法。想了解的朋友可以查看这篇文章。同时&#xff0c;希望我的文章能帮助到你&#xff0c;如果觉得我的文章写的不错&#xff0c;请留下你宝贵的点赞&#…...

【SpringBoot XSS存储漏洞 拦截器】Java纯后端对于前台输入值的拦截校验实现 一个类加一个注解结束

先看效果&#xff1a; 1.js注入拦截&#xff1a; 2.sql注入拦截 生效只需要两步&#xff1a; 1.创建Filter类&#xff0c;粘贴如下代码&#xff1a; package cn.你的包命.filter; import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.IO…...

【微信小程序】canvas开发笔记

【微信小程序】canvasToTempFilePath:fail fail canvas is empty 看说明书 最好是先看一下官方文档点此前往 如果是canvas 2d 写canvas: this.canvas,&#xff0c;如果是旧版写canvasId: ***, 解决问题 修改对应的代码&#xff0c;如下所示&#xff0c;然后再试试运行&#x…...

TripoSR: Fast 3D Object Reconstruction from a Single Image 论文阅读

1 Abstract TripoSR的核心是一个基于变换器的架构&#xff0c;专为单图像3D重建设计。它接受单张RGB图像作为输入&#xff0c;并输出图像中物体的3D表示。TripoSR的核心包括&#xff1a;图像编码器、图像到三平面解码器和基于三平面的神经辐射场&#xff08;NeRF&#xff09;。…...

u盘为什么一插上电脑就蓝屏,u盘一插电脑就蓝屏

u盘之前还好好的&#xff0c;可以传输文件&#xff0c;使用正常&#xff0c;但是最近使用时却出现问题了。只要将u盘一插入电脑&#xff0c;电脑就显示蓝屏。u盘为什么一插上电脑就蓝屏呢?一般&#xff0c;导致的原因有以下几种。一&#xff0c;主板的SATA或IDE控制器驱动损坏…...

【Redis】redis面试相关积累

Redis到底是多线程还是单线程&#xff1f; Redis 在设计上是单线程的&#xff0c;这意味着 Redis 服务器在任何给定时刻只能执行一个命令。然而&#xff0c;这并不意味着 Redis 无法利用多核 CPU&#xff0c;因为 Redis 使用了一些技术来提高性能和并发性&#xff0c;例如非阻…...

【Linux】进程的状态(运行、阻塞、挂起)详解,揭开孤儿进程和僵尸进程的面纱,一篇文章万字讲透!!!!进程的学习②

目录 1.进程排队 时间片 时间片的分配 结构体内存对齐 偏移量补充 对齐规则 为什么会有对齐 2.操作系统学科层面对进程状态的理解 2.1进程的状态理解 ①我们说所谓的状态就是一个整型变量&#xff0c;是task_struct中的一个整型变量 ②.状态决定了接下来的动作 2.2运行状态 2.…...

前端js基础知识(八股文大全)

一、js的数据类型 值类型(基本类型)&#xff1a;数字(Number)、字符串&#xff08;String&#xff09;、布尔(Boolean)、对空&#xff08;Null&#xff09;、未定义&#xff08;Undefined&#xff09;、Symbol,大数值类型(BigInt) 引用数据类型&#xff1a;对象(Object)、数组…...

316_C++_xml文件解析成map,可以放到表格上 + xml、xlsx文件互相解析

xml文件例如&#xff1a; <?xml version"1.0" encoding"UTF-8" standalone"yes"?> <TrTable> <tr id"0" label"TR_PB_CH" text"CH%2"/> <tr id"4" label"TR_PB_CHN"…...

未来汽车硬件安全的需求(2)

目录 4.汽车安全控制器 4.1 TPM2.0 4.2 安全控制器的硬件保护措施 5. EVITA HSM和安全控制器结合 6.小结 4.汽车安全控制器 汽车安全控制器是用于汽车工业安全关键应用的微控制器。 他们的保护水平远远高于EVITA HSM。今天的典型应用是移动通信&#xff0c;V2X、SOTA、…...

html+javascript,用date完成,距离某一天还有多少天

图片展示: html代码 如下: <style>* {margin: 0;padding: 0;}.time-item {width: 500px;height: 45px;margin: 0 auto;}.time-item strong {background: orange;color: #fff;line-height: 100px;font-size: 40px;font-family: Arial;padding: 0 10px;margin-right: 10px…...

跟bug较劲的第n天,undefined === undefined

前情提要 场景复现 看到这张图片&#xff0c;有的同学也许不知道这个冷知识&#xff0c;分享一下&#xff0c;是因为我在开发过程中踩到的坑&#xff0c;花了三小时排查出问题的原因在这&#xff0c;你们说值不值。。。 我分享下我是怎么碰到的这个问题&#xff0c;下面看代码…...

数据结构_基于链表的通讯录

顺序表的源代码需要略作修改&#xff0c;如下 将数据类型改为通讯录的结构体。注释掉打印&#xff0c;查找的函数。 SList.h #define _CRT_SECURE_NO_WARNINGS 1#include<stdio.h> #include<stdlib.h> #include<assert.h> #include"Contact.h"ty…...

jenkins+gitlab配置

汉化 1、安装Localization: Chinese (Simplified)插件 &#xff08;此处我已安装&#xff09; &#xff08;安装完成后重启jenkins服务即可实现汉化&#xff09; 新增用户权限配置 1、安装插件 Role-based Authorization Strategy 2、全局安全配置 3、配置角色权限 4、新建…...

【Labview】虚拟仪器技术

一、背景知识 1.1 虚拟仪器的定义、组成和应用 虚拟仪器的特点 虚拟仪器的突出特征为“硬件功能软件化”&#xff0c;虚拟仪器是在计算机上显示仪器面板&#xff0c;将硬件电路完成信号调理和处理功能由计算机程序完成。 虚拟仪器的组成 硬件软件 硬件是基础&#xff0c;负责将…...

IvorySQL 3.2原理解析|与Oracle 12c XML函数兼容性的实现机制

[发行日期&#xff1a;2024年4月11日] IvorySQL 3.2基于PostgreSQL 16.2&#xff0c;引入了多种Oracle XML函数的全面兼容性功能&#xff0c;同时修复了多个问题&#xff0c;更多信息请参考文档网站。 >>>新版本体验链接&#xff1a; https://docs.ivorysql.org/cn…...

SpringBoot + Dobbo + nacos

SpringBoot Dobbo nacos 一、nacos https://nacos.io/zh-cn/docs/quick-start.html 1、下载安装包 https://github.com/alibaba/nacos/releases/下载后在主目录下&#xff0c;创建一个logs的文件夹&#xff1a;用来存日志 2、启动nacos 在bin目录下打开cmd运行启动命令&a…...

学习笔记-微服务基础(黑马程序员)

框架 spring cloudspring cloud alibaba Eureka eureka-server 注册中心 eureka-client 客户端每30s发送心跳服务 服务消费者服务提供者 server 依赖 <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-star…...

每日Bug汇总--Day05

Bug汇总—Day05 一、项目运行报错 二、项目运行Bug 1、**问题描述&#xff1a;**前端将从后台查询的数据作为参数进行get请求&#xff0c;参数为空 原因分析&#xff1a; 这种写法可能只支全局的参数调用方法的传参响应 代码实现 if (this.jishiName) {this.$http({url…...

docker、ctr、crictl命令对比

命令dockerctr&#xff08;containerd&#xff09;crictl&#xff08;kubernetes&#xff09;查看运行的容器docker psctr task ls/ctr container lscrictl ps查看镜像docker imagesctr image lscrictl images查看容器日志docker logs无crictl logs查看容器数据信息docker insp…...

uniapp 编译后分包下静态图片404问题解决方案

如上图官方说明&#xff1a; 在分包下建立一个static文件夹即可&#xff1a; 分包内代码引用图片 <image src"/分包名称/img/图片名称"></image> <image src"/dataView/img/图片名称"></image>...

第十二届蓝桥杯大赛软件赛省赛Java 大学 B 组题解

1、ASC public class Main {public static void main(String[] args) {System.out.println(...

关于openai和chatgpt、gpt-4、PyTorch、TensorFlow 两者和Transformers的关系

近两年&#xff0c;随着人工智能的火爆&#xff0c;不论通过哪个渠道&#xff0c;相信我们都听说过openai、gpt等这类名词&#xff0c;那么它们到底是什么意思&#xff0c;请看下文。 openai:是一家人工智能公司&#xff1b; openai-api&#xff1a;是openai提供的api&#xf…...

C 共用体

共用体是一种特殊的数据类型&#xff0c;允许您在相同的内存位置存储不同的数据类型。您可以定义一个带有多成员的共用体&#xff0c;但是任何时候只能有一个成员带有值。共用体提供了一种使用相同的内存位置的有效方式。 定义共用体 为了定义共用体&#xff0c;您必须使用 u…...

什么网站可做浏览器首页/网站开发培训

11月17日&#xff0c;阿里巴巴集团发布2023财年二季度财报。于2022年9月30日止季度&#xff0c;抵销跨分部交易前&#xff0c;菜鸟本季度营业收入同比增长26%至182.82亿元&#xff0c;外部收入占比进一步提升至73%。通过持续建设高质量的产业互联网&#xff0c;做全球化的长期主…...

asp网站制作教程/willfast优化工具下载

来到这边,开始工作后,才发现.有的时候,心态变了.一切都会改变.以前总是把自己会的技术挂在嘴边.而这次,更多的是踏踏实实的做出来.没有什么可骄傲的.一切都没有. 中午在机房里呆了一中午,又一次熟悉了设备及常用命令.在听完郭老师的培训后,才发现,自己是那么的无知.知识的深度及…...

王爷王妃她红鸾心动了/网站做优化一开始怎么做

https://tech.meituan.com/2018/01/19/mybatis-cache.html https://blog.csdn.net/chi_666/article/details/107052896 一&#xff1a; 只能在【只有单表操作】的表上使用缓存 不只是要保证这个表在整个系统中只有单表操作&#xff0c;而且和该表有关的全部操作必须全部在一…...

无锡企业网站建设/推广关键词如何优化

ls /bin /usr/bin | sort | uniq | less 上面这条命令的实际效果是&#xff1a; 获得 ls /bin /usr/bin 的 output将上述 output 进行 sort (排序)&#xff0c;并去掉重复项 (uniq)将经过以上处理的 output 作为 less 命令的 input&#xff0c;输出在屏幕上相反地&#xff0c;如…...

深圳网站 建设信科网络/营业推广名词解释

历时五天的北京之旅告一段落。 五天印象最深的就是北京地铁13号实在太拥挤了。但是&#xff0c;由于师哥师姐以及同学之间互相照顾&#xff0c;所以五天其实说实话挺舒服(*^__^*)。有幸出去见识了一下外面的情况&#xff0c;并且有幸结识了Mkey3G。无论从事与否&#xff0c;至少…...

服务器购买网站/网络营销策划案怎么写

以前用在DateTimePicker一般都是只显示年月日&#xff0c;这次需要显示时间和分钟&#xff0c;结果发现一直是显示12小时制的时间。 一番搜索找到答案记录在这里&#xff1a; 首先要使用自定义的格式显示&#xff0c;肯定是要把format:属性值设为&#xff1a;custom 其次…...