[TCP协议]基于TCP协议的字典服务器

news2024/11/15 21:58:59

目录

1.TCP协议简介:

2.TCP协议在Java中封装的类以及方法

3.字典服务器

3.1服务器代码:

3.2客户端代码:


1.TCP协议简介:

TCP协议是一种有连接,面向字节流,全双工,可靠的网络通信协议.它相对于UDP协议来说有以下几点好处:

1.它是可靠传输,相比于UDP协议,传输的数据更加可靠.当然这里的可靠是相对的,并不是真的万无一失.我们会在后面的博客中给大家详细介绍TCP协议的可靠传输.

2.它传输的字节流文件没有大小限制,不像UDP协议,一次只能传输64kb的报文数据.

但是也有缺点:

1.开销大,需要对连接的建立与维护,以及确认数据报的确认和重传,会增加网络开销.

2 传输效率低;由于可靠性和流量控制,会对传输效率造成一定的影响

基于这些特性:因此TCP协议不适用于实时性要求高的程序,适合数据库访问,网络游览器,文件传输,电子邮件等应用.

2.TCP协议在Java中封装的类以及方法

TCP协议在Java中有两个api,分别是SeverSocket和Socket

顾名思义,SeverSocket是给服务器用的api,它仅限于服务器使用,而Socket服务器和客户端都可以使用.

SeverSocket构造方法:

方法签名方法说明
ServerSocket(int port)创建一个服务端流套接字Socket,并绑定到指定端口

SeverSocket的方法:

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

Socket 是客户端Socket,或服务端中接收到客户端建立连接(accept方法)的请求后,返回的服务端Socket。
不管是客户端还是服务端Socket,都是双方建立连接以后,保存的对端信息,及用来与对方收发数据的。

Socket的构造方法:

方法签名方法说明
Socket(String host, int
port)
创建一个客户端流套接字Socket,并与对应IP的主机上,对应端口的
进程建立连接

Socket的方法:

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

3.字典服务器

下面我们基于这两个api做一个简单的字典服务器.它类似于翻译软件,当我们去输入中文字符的时候,会返回并且打印与之对应的英文字符.

为了更方便大家理解,我们先做一个在之前的文章提过的回显服务器:

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.Arrays;
import java.util.Scanner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class TcpEchoSever {
    ServerSocket serverSocket = null;
    public TcpEchoSever(int port) throws IOException { //指定服务器的端口号
        serverSocket = new ServerSocket(port);
    }
    public void strat() throws IOException {
        System.out.println("服务器启动");
        while (true){
            Socket socket = serverSocket.accept(); //通过acccept方法获取到我们的客户端信息并保存到socket中
            Thread t = new Thread(()->{  //这里使用多线程是为了让不同的客户端都分配一个线程,以免因为一个客户端让它阻塞而别的客户端不能访问
                try {
                    accress(socket);
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            });
            t.start();

        }
    }

    public void accress(Socket socket) throws IOException {
        try (InputStream inputStream = socket.getInputStream();
             OutputStream outputStream = socket.getOutputStream()) { //字节流,有点类似于文件操作
            System.out.printf("[客户端连接%s:%d]\n",socket.getInetAddress(),socket.getPort());
            while (true) {
                {   Scanner inputScnner = new Scanner(inputStream);
                    if (!inputScnner.hasNext()) {
                        System.out.println("连接中断");
                        break;
                    }
                    String request = inputScnner.next(); //读取数据
                    String reqonse = func(request); //把数据进行服务器端的计算请求
                    PrintWriter writer  = new PrintWriter(outputStream);//将响应返回给客户端
                    writer.println(reqonse);
                    writer.flush();//这里的flush是为了把缓冲池里的数据给刷新
                    System.out.printf("[%s:%d]\n,request : %s ,reqonse : %s"
                    ,socket.getInetAddress(),socket.getPort(),request,reqonse);//打印日志
                }
            }
        }finally {
            socket.close();//防止客户端过多,造成文件资源泄露,让文件描述符表满了
        }
    }
    public String func(String request){
        return request;
    }

    public static void main(String[] args) throws IOException {
        TcpEchoSever tcpEchoSever = new TcpEchoSever(9090);
        tcpEchoSever.strat();
    }
}

我们直接继承这个服务器代码,并且重写func方法,将我们的字典加入进去

3.1服务器代码:

import java.io.IOException;
import java.util.HashMap;

public class TcpDcarySever extends TcpEchoSever{
    HashMap<String,String> hashMap = new HashMap<>();

    public TcpDcarySever(int port) throws IOException {
        super(port);
        hashMap.put("小狗","dog");
        hashMap.put("小猫","cat");
        hashMap.put("小坤","chincken");
    }
    @Override
    public String func(String request) {
        return hashMap.getOrDefault(request,"没找到,请重新查找");
    } //重写func方法
    public static void main(String[] args) throws IOException {
        TcpDcarySever tcpDcarySever = new TcpDcarySever(9091);
        tcpDcarySever.strat();
    }
}

3.2客户端代码:

步骤都在注释里

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 TcpEchoClient {
    Socket socket = null;
    public TcpEchoClient(String SeverIp,int port) throws IOException { //体现了TCP协议的有连接 得在构造方法中把目的服务器的IP地址和端口号指定
        socket = new Socket(SeverIp , port);
    }
    private void start(){
        System.out.println("客户端启动");
        try (InputStream inputStream = socket.getInputStream();
             OutputStream outputStream = socket.getOutputStream()){ //一样是面向字节流 ,所以和文件操作类似
            Scanner scanner = new Scanner(System.in);
            Scanner inpuscnner = new Scanner(inputStream);
            PrintWriter writer = new PrintWriter(outputStream); 
            while (true){
                if(!scanner.hasNext()){
                    break;
                }
                String requeset = scanner.next();//从控制台读取数据
                writer.println(requeset);//发送请求
                writer.flush();//刷新缓冲池
                String reqonse = inpuscnner.next();//从服务器端拿到请求并构造成字符串
                System.out.println(reqonse);
            }

        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public static void main(String[] args) throws IOException {
        TcpEchoClient tcpEchoClient = new TcpEchoClient("127.0.0.1",9091);//指定目标的IP地址和端口号
        tcpEchoClient.start();
    }
}

结果演示:

启动服务器:

启动客户端观察服务器的情况:

输入中文字符看看:

此时客户端是这样的

为了观察多线程的作用,我们再次启动另一个客户端:

可以看到另一个客户端也脸上了

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1415469.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

在ubuntu上在安装Squid代理服务器

Squid 是一个代理和缓存服务器&#xff0c;它将请求转发到所需的目的地&#xff0c;同时保存请求的内容&#xff0c;当你再次请求相同内容时&#xff0c;他可以向你提供缓冲内容&#xff0c;从而提高访问速度。Squid代理服务器目前支持的协议有&#xff1a;http、SSL、DNS、FTP…

【机组】单元模块的软件简介和安装

​&#x1f308;个人主页&#xff1a;Sarapines Programmer&#x1f525; 系列专栏&#xff1a;《机组 | 模块单元实验》⏰诗赋清音&#xff1a;云生高巅梦远游&#xff0c; 星光点缀碧海愁。 山川深邃情难晤&#xff0c; 剑气凌云志自修。 目录 【软件简介和安装】 1 性能特…

JVM篇:垃圾回收算法

标记清除 通过遍历GC Root后得到不再被引用的对象&#xff0c;对没被引用的对象做一个标记处理&#xff0c;然后对其进行清除。 优点&#xff1a;速度快 缺点&#xff1a;会产生内存碎片&#xff0c;可能会导致空闲的内存足够保存对象&#xff0c;但由于不连续而保存失败。 标…

Linux操作系统运维-用户与用户组管理

Linux操作系统运维-用户与用户组管理 用户种类与标识查看 超级用户&#xff08;root&#xff09;&#xff1a;可以不受限制地执行所有操作&#xff0c;拥有系统最高权限&#xff0c;修改系统设置与管理用户均需要root权限系统用户&#xff08;system&#xff09;&#xff1a;…

S275智慧煤矿4G物联网网关:矿山开采的未来已来

随着经济发展煤矿需求不断激增&#xff0c;矿山矿井普遍处于偏远山区&#xff0c;生产管理、人员安全、生产效率是每个矿山矿井都需要考虑的问题&#xff0c;利用网关对现场终端设备连接组网&#xff0c;实现智慧煤矿远程管理。 各矿山矿井分布范围比较广泛&#xff0c;户外环…

Leetcode541反转字符串Ⅱ(java实现)

我们今天分享的题目是字符串反转的进阶版反转字符串Ⅱ。 我们首先来看题目描述&#xff1a; 乍一看题目&#xff0c;有种懵逼的感觉&#xff0c;不要慌&#xff0c;博主来带着你分析题目&#xff0c;题目要求&#xff1a; 1. 每隔2k个字符&#xff0c;就对2k字符中的前k个字符…

【mongoDB】创建用户账号和权限

使用use database_name 命令创建或切换到一个数据库 查看用户 show users 输入该命令后&#xff0c;无数据表示该数据库没有用户 创建用户 user:" freedom " 表示用户名为freedom pwd:" 123456 ” 表示密码为123456 roles:[" root "] …

pcl之滤波器(三)

pcl滤波器 pcl一共是有十二个主要模块&#xff0c;详细了解可以查看官网。https://pcl.readthedocs.io/projects/tutorials/en/latest/#basic-usage 今天学习一下pcl的滤波器模块。 滤波器模块&#xff0c;官网一共是提供了6个例程&#xff0c;今天看第五个、第六个。 从一…

CSS设置单行文字水平垂直居中的方法

<!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>单行文字水平垂直居中</title><style>div {/* 给div设置宽高 */width: 400px;height: 200px;margin: 100px auto;background-color: red;/…

【深度学习每日小知识】Bias 偏差

计算机视觉是人工智能的一个分支&#xff0c;它使机器能够解释和分析视觉信息。然而&#xff0c;与任何人造技术一样&#xff0c;计算机视觉系统很容易受到训练数据产生的偏差的影响。计算机视觉中的偏见可能会导致不公平和歧视性的结果&#xff0c;从而使社会不平等长期存在。…

[GYCTF2020]Ezsqli1

打开环境&#xff0c;下面有个提交表单 提交1&#xff0c;2有正确的查询结果&#xff0c;3以后都显示Error Occured When Fetch Result. 题目是sql&#xff0c;应该考察的是sql注入 简单fuzz一下 发现information_schema被过滤了&#xff0c;猜测是盲注了。 测试发现只要有东…

【MySQL】学习如何通过DML更新数据库的数据

&#x1f308;个人主页: Aileen_0v0 &#x1f525;热门专栏: 华为鸿蒙系统学习|计算机网络|数据结构与算法 ​&#x1f4ab;个人格言:“没有罗马,那就自己创造罗马~” #mermaid-svg-QIqURn9fNFMjLD9l {font-family:"trebuchet ms",verdana,arial,sans-serif;font-siz…

火车票车票查询-Python

一、相关代码 # Time: 2024/1/22 20:24 # Author: 马龙强 # File: 实现12306查票购票.py # software: PyCharm """网址&#xff1a;https://www.12306.cn/index/ 数据&#xff1a;车次信息 查票链接&#xff1a;https://kyfw.12306.cn/otn/leftTicket/queryE?…

四、vtk相机类vtkCamera的使用

在三维渲染场景中,相机好比观众的眼睛,人站立的位置影响事物的大小,视角的不同影响看到事物的范围,目光的朝向影响看到事物的正反。 vtkCamera负责把三维场景投影到二维平面,如屏幕、图像等。 下图为相机投影示意图: 相机位置:即相机所在的位置,用方法vtkCamera::Se…

【Linux】进程间通信概念 | 匿名管道

文章目录 一、什么是进程间通信进程间通信的概念进程间通信的目的进程间通信的分类进程间通信的本质 二、什么是管道三、匿名管道匿名管道的原理✨站在内核角度理解管道✨站在文件描述符角度理解管道 pipe系统调用fork后在父子进程间使用管道通信代码实现 匿名管道的读写规则管…

【论文笔记】《Learning Deconvolution Network for Semantic Segmentation》

重要说明&#xff1a;严格来说&#xff0c;论文所指的反卷积并不是真正的 deconvolution network 。 关于 deconvolution network 的详细介绍&#xff0c;请参考另一篇博客&#xff1a;什么是Deconvolutional Network&#xff1f; 一、参考资料 Learning Deconvolution Netwo…

【C语言刷题系列】交换两个变量的三种方式

文章目录 1.使用临时变量&#xff08;推荐&#xff09; 2.相加和相减的方式&#xff08;值较大时可能丢失数据&#xff09; 3.按位异或运算 本文所属专栏C语言刷题_倔强的石头106的博客-CSDN博客 两个变量值的交换是编程中最常见的问题之一&#xff0c;以下将介绍三种变量的…

数据结构(1)--> 顺序表

定义&#xff1a; 顺序表存储定义&#xff1a; 把逻辑上相邻的数据元素存储在物理上相邻的存储单元中的存储结构&#xff0c;顺序表功能的实现借助于数组&#xff0c;通过对数组进行封装&#xff0c;从而实现增删查改的功能&#xff0c;严格意义上来说&#xff08;数组无法实现…

python在线聊天室(带聊天保存)

python Socket在线聊天室(带聊天保存) 需求功能 1.聊天信息保存功能(服务端会把信息保存到一个txt里面) 2.使用pyqt5框架作为一个可视化界面 3.具备一个服务端和多个客户端的功能 4.具备离线加入黑名单(离线踢出) 5.具备在线加入黑名单(在线加入黑名单被踢出) 6.具备群聊功能…

JasperReports渲染报表文件时候,读取图片报错:Byte data not found at:xxx.png.\r\n\tat

目录【知识星球】 1.1、错误描述 1.2、解决方案 1.1、错误描述 最近在工作中&#xff0c;使用JasperReports报表比较多一些&#xff0c;有次线上环境里面运行报错&#xff0c;查看报错日志&#xff0c;如下所示&#xff1a; net.sf.jasperreports.engine.JRException: Byte…