udp/tcp回显网络编程

udp
DatagramSocket 

用于接收和发送udp数据报


构造方法:

  • DatagramSocket():创建一个UDP数据报套接字的Socket,绑定到本地上 一个随机可用端口上,一般用于客户端
  • DatagramSocket(int port):创建一个UDP数据报套接字的Socket,绑定到指定端口上,一般适用于服务器端

DatagramSocket方法:

  • void receive(DatagramPacket p):接收套接字数据报p,如果此时还没有发送,便会阻塞
  • void send(DatagramPacket p):发送套接字数据报p,不会阻塞,直接发送
  • void close():关闭此数据报套接字
DatagramPacket:

udp发送和接收的数据报形式


构造方法:

  • DatagramPacket(byte[] buf,int length):构造一个DatagramPacket对象来接收发送来到数据报,将数据内容放在第一个字节数组中,第二个参数是指定接收内容的长度。(用于接收时)
  • DatagramPacket(byte[] buf,int offset,int length,SocketAddress address):接收发来的数据报,并将内容放进buf数组中,选中需要截取内容的索引[offset,length)。address:指定目的主机的ip和端口号。(用于发送时)

DatagramPacket方法:

  • getSocketAddress():获取发送端的ip地址。
  • getPort():获取发送端的端口
  • byte[] getData():获取数据报中的内容

udp回显服务器实现:
服务器端:
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
import java.nio.charset.StandardCharsets;

public class udpServer {
    //服务器端
    private DatagramSocket socket = null;

    public udpServer(int port) throws SocketException {
        socket = new DatagramSocket(port);
    }

    public void start() throws IOException {
        //System.out.println(socket.getPort());
        //returns the port to which the socket is connected  未连接套接字时 返回-1
        //如果想得到服务器端的端口 要使用socket.getLocalPort()
        System.out.println("服务器启动");
        //构建一个DatagramPacket来接收客户端发来的消息
        while(true){
            //创建一个DatagramPacket填充对象,用来接收从客户端发送来的数据报
            DatagramPacket reqPacket = new DatagramPacket(new byte[4096],4096);

            //如果没有数据报发送,receive发送会阻塞等待
            socket.receive(reqPacket);

            //转换成我们看得懂的字符串形式 ----- 客户端发送来的请求
            String request = new String(reqPacket.getData(),0,reqPacket.getLength());

            //服务器端做出响应
            String res = RESPONSE(request);

            //构建一个DatagramPacket将响应后的结果发送回客户端
            //注意需要有客户端socketAddress
            DatagramPacket respPacket = new DatagramPacket(res.getBytes(StandardCharsets.UTF_8),0,res.getBytes().length,
                    reqPacket.getSocketAddress());

            //发送数据报
            socket.send(respPacket);
            System.out.println("服务器端口:"+socket.getLocalPort()+": 客户端[ip:"+respPacket.getAddress()+" 端口:"+reqPacket.getPort()
                                +"] req:"+request+" res:"+res);
        }
    }
    public String RESPONSE(String req){
        return req;
    }

    public static void main(String[] args) throws IOException {
        udpServer server = new udpServer(8080);
        server.start();
    }
}

值得注意的是:DatagramSocket的getPort/getAddress方法,返回的都是连接方的端口和ip,并不是本地的。而DatagreamPacket的getPort/getAddress方法,返回的都是本地的端口和ip地址。如果你还没有连接成功时,打印socket.getPort(),虽然这时候你已经给出了指定端口,但这个方法的返回值是连接端的,还没连接时返回-1


客户端
import java.io.IOException;
import java.net.*;
import java.nio.charset.StandardCharsets;
import java.util.Scanner;

public class udpClient {
    //目的端ip
    private String severIp;
    //目的端端口
    private int severPort;
    private DatagramSocket socket;

    public udpClient(String severIp,int severPort) throws SocketException {
        socket = new DatagramSocket();
        this.severIp = severIp;
        this.severPort = severPort;
    }

    public void start() throws IOException {
        Scanner sc = new Scanner(System.in);
        System.out.println("客户端启动");
        while(true){
            System.out.print(">>");
            String request = sc.nextLine();
            if(request.equals("exit")){
                System.out.println("退出");
                socket.close();
                return;
            }
            //给出消息发出的目的端ip和端口 (服务器ip端口)
            DatagramPacket reqPacket = new DatagramPacket(request.getBytes(StandardCharsets.UTF_8),request.getBytes().length
            ,InetAddress.getByName(severIp),severPort);

            //发送
            socket.send(reqPacket);

            //接收响应
            DatagramPacket responsePacket = new DatagramPacket(new byte[4096],4096);
            socket.receive(responsePacket);

            //转换成字符串形式
            String res = new String(responsePacket.getData(),0, responsePacket.getLength());
            //打印响应
            System.out.println(res);
        }
    }

    public static void main(String[] args) throws IOException {
        udpClient client = new udpClient("127.0.0.1",8080);
        client.start();
    }
}

注意:当传服务器端的ip地址时,此时我们这里给的是一个字符串,但参数接收的是一个32位整数形式,所以我们需使用InetAddress.getName(String hostage)做一下转换


tcp
SeverSocket 

服务器端Socket API


构造方法:

  • SeverSccket(int port):创建一个服务器端流套接字Socket,并绑定到指定端口

SeverSocket的方法:

  • Socket accept():监听指定端口(创建时绑定的端口),如果有客户端连接后,返回一个服务端Socket对象,否则阻塞等待
  • void close():关闭套接字
Socket

客户端Socket,或服务器端的accept方法收到有客户端连接后返回的服务端Socket

无论是客户端还是服务器端,都是连接建立后,保存对端的信息


构造方法:

Socket(String severIp,int severPort):创建一个客户端Socket,与对应的主机端口建立连接


Socket的方法:

  • InetAddress():返回套接字所连接的地址
  • InputStream getInputStream():
  • OutputStream getOutStream():

ps:tcp是面向字节流传输的


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 tcpSever {
    private ServerSocket socket;

    public tcpSever(int port) throws IOException {
        socket = new ServerSocket(port);
    }

    public void start() throws IOException {
        System.out.println("服务器启动");
        //与服务器建立连接 返回一个服务器端Socket
        Socket clickClient = socket.accept();

        processConnection(clickClient);
    }
    public void processConnection(Socket clientSocket){
        System.out.println("客户端上线[ip:"+clientSocket.getInetAddress().toString()+"  port:"+clientSocket.getPort()+"]");
        try(InputStream inputStream = clientSocket.getInputStream(); OutputStream outputStream = clientSocket.getOutputStream()) {
            while(true){
                //读取结果
                //输入流 会等待客户端输入东西 阻塞在这里 (通过Scanner的方法都会造成阻塞)
                Scanner sc = new Scanner(inputStream);
                if(!sc.hasNext()){
                    //没有数据了 断开连接
                    System.out.println("客户端下线[ip:"+clientSocket.getInetAddress()+"  port:"+clientSocket.getPort());
                    socket.close();
                    break;
                }
                //遇到换行/空白结束
                String req = sc.next();

                //服务器响应
                String resp = process(req);

                //OutputStream没有写String的方法
                //1.将其转换成字节数组
                //2.使用PrintWriter-----打印流-----字符打印流/字节打印流
                PrintWriter printWriter = new PrintWriter(outputStream);
                printWriter.println(resp);
                printWriter.flush();
                System.out.println("客户端:[req:"+req+" resp:"+resp+" ip:"+clientSocket.getInetAddress()+" port:"+clientSocket.getPort()+"]");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    public String process(String req){
        return req;
    }

    public static void main(String[] args) throws IOException {
        tcpSever sever = new tcpSever(8080);
        sever.start();
    }
}

客户端
import java.io.IOException;
import java.net.*;
import java.nio.charset.StandardCharsets;
import java.util.Scanner;

public class udpClient {
    //目的端ip
    private String severIp;
    //目的端端口
    private int severPort;
    private DatagramSocket socket;

    public udpClient(String severIp,int severPort) throws SocketException {
        socket = new DatagramSocket();
        this.severIp = severIp;
        this.severPort = severPort;
    }

    public void start() throws IOException {
        Scanner sc = new Scanner(System.in);
        System.out.println("客户端启动");
        while(true){
            System.out.print(">>");
            String request = sc.nextLine();
            if(request.equals("exit")){
                System.out.println("退出");
                socket.close();
                return;
            }
            //给出消息发出的目的端ip和端口 (服务器ip端口)
            DatagramPacket reqPacket = new DatagramPacket(request.getBytes(StandardCharsets.UTF_8),request.getBytes().length
            ,InetAddress.getByName(severIp),severPort);

            //发送
            socket.send(reqPacket);

            //接收响应
            DatagramPacket responsePacket = new DatagramPacket(new byte[4096],4096);
            socket.receive(responsePacket);

            //转换成字符串形式
            String res = new String(responsePacket.getData(),0, responsePacket.getLength());
            //打印响应
            System.out.println(res);
        }
    }

    public static void main(String[] args) throws IOException {
        udpClient client = new udpClient("127.0.0.1",8080);
        client.start();
    }
}

注意:

  1. 在tcp的Socket中,ip地址可以直接传字符串类型的,不需要像udpSocket那样转成32位整数形式
  2. 我们读通过next()读,写通过println写。这是设计好了的。使换行符变成我们的消息隔断符,使我们知道每一段消息的头和尾,解决粘包问题
  3. 在运行tcp回显服务器时,必须先开服务器端,再开客户端因为如果先开客户端的话,此时没有服务器与之相连,会抛异常------对应的即为tcp的是有连接的

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Proxmox VE 8 用SDN隔离用户网络

作者:田逸(formyz) 最新发布的Proxmox VE(以下简称PVE) 8在Web管理后台集成了易于操作的SDN(软件定义网络)功能插件,其实质是对不同的PVE用户指定不同的网络,进行逻辑隔离…

将要上市的自动驾驶新书《自动驾驶系统开发》中摘录各章片段 4

第十三章 车联网 数字化设备正变得越来越普遍并且相互联系。这些设备向数字生态系统智能部分的演进创造了迄今为止尚未解决安全问题的新颖应用。一个特定的例子是车辆,随着车辆从简单的交通方式发展到具有新的感知和通讯功能的智能实体,就成为智能城市的…

屏蔽罩材质和厚度对屏蔽效能的影响

​ 一.屏蔽效能的影响因素 屏蔽效能的影响因素主要有两个方面:屏蔽材料的特性和厚度;如下图所示,电磁波经过不同媒介时,会在分界面形成反射,穿过界面的电磁波一部分被反射回去,这部分能量损失…

偶然发现了Python的一个BUG。。。

一般情况下,dict(id1, **{id: 1})这句代码应该报TypeError。但如果在捕获了其他异常的情况下,再来执行这句代码,却是会报KeyError,如下图: Python3.10和Python3.9也能复现该情况,正当我摩拳踩掌&#xff0c…

百度下拉框负面信息如何删除?

百度头条360等搜索引擎,作为人们获取信息的主要途径之一。然而,一些知名的企业或个人可能会面临在搜索的下拉框中出现负面信息的问题,这可能对其声誉和形象造成不良影响。小马识途营销顾问根据自身从业经验,针对这类情况提出以下建…

【精品毕设推荐】基于JSP物流信息网的设计与实现

点击免费下载原文及代码、PPT 摘要 本文讲述了基于JSP物流信息网的设计与实现。该系统使用java语言开发,使系统具有更好的平台性和可扩展性。 该系统实现了用户登录、注册、查询快递信息、快递公司注册成为合作伙伴以及系统管理员对信息进行管理等功能。系统的主…

LeetCode 234.回文链表

题目描述 给你一个单链表的头节点 head ,请你判断该链表是否为 回文链表 。如果是,返回 true ;否则,返回 false 。 示例 1: 输入:head [1,2,2,1] 输出:true示例 2: 输入&#xff…

解决windows中的WSL Ubuntu子系统忘记root密码和用户密码问题

1、以管理员身份运行PowerShell 2、在powershell中执行wsl.exe --user root wsl.exe --user root如果出现了上面的报错,则需要运行步骤3、4,然后在执行步骤5改密码,如果没有出错,请直接跳到第5步改密码操作!&#xff…

一分钱不花从HTTP升级到HTTPS

HTTP升级到HTTPS是一个涉及安全性和技术实施的过程,主要目的是为了提升网站数据传输的安全性,防止数据被窃取或篡改。以下是一些关于从HTTP升级到HTTPS的技术性要点和步骤概述,结合上述信息资源: 一、理解HTTPS的重要性 HTTPS (…

微信IDE vscode插件:获取插件位置,并打开文件

背景 有没有觉得在微信开发工具里面添加一些插件可以很方便。因为微信IDE的编辑本身是依赖vscode开发,所以编写vscode插件自然可以在微信IDE使用。这样做好处就是可以满足到自己一些开发使用习惯。 1.获取插件的目录位置 那么如何获取插件里面的目录,…

【精】hadoop、HIVE大数据从0到1部署及应用实战

目录 基本概念 Hadoop生态 HIVE hdfs(hadoop成员) yarn(hadoop成员) MapReduce(hadoop成员) spark flink storm HBase kafka ES 实战 安装并配置hadoop 环境准备 准备虚拟机 安装ssh并设置免密登录 安装jdk 安装、配置并启动hadoop 添加hadoop环境变量&…

STM32F1之FLASH闪存

目录 1. 简介 2. 闪存模块组织 3. FLASH基本结构 4. FLASH解锁 5. 使用指针访问存储器 6. 程序存储器全擦除 7. 程序存储器页擦除 8. 程序存储器编程 9. 选项字节 1. 简介 STM32F1系列的FLASH包含程序存储器、系统存储器和选项字节三个部分,通过…

MapReduce笔记

实现分布式的作用: 通过并行处理提高能力通过复制机制进行容错处理与传感器等物理设备的分布相匹配通过隔离实现安全 难点: 许多并行的部件,他们之间有复杂的相互作用必须应对处理部分故障难以实现性能潜力 容错 1000多台服务器、庞大的网络…

【busybox记录】【shell指令】b2sum

目录 内容来源: 【GUN】【b2sum】指令介绍 【busybox】【b2sum】指令介绍 【linux】【b2sum】指令介绍 使用示例: BLAKE2摘要(512bit) - 默认输出 BLAKE2摘要(512bit) - 指定校验和长度 BLAKE2摘要…

Python量化炒股的数据信息获取—获取沪深股市每日成交概况信息

Python量化炒股的数据信息获取—获取沪深股市每日成交概况信息 沪深股市每日成交概况信息,都存放在STK_EXCHANGE_TRADE_INFO表中,该表保存在finance包中。要查看表中的数据信息,需要使用query()函数。 单击聚宽JoinQuant量化炒股平台中的“…

还有谁……想知道“线下与线上布局之间的本质区别”

还有谁……想知道 线下与线上布局之间的本质区别 hello,亲爱的你们好.… 我是你们的好朋友,正博,今天是非常特殊的一天,给每一位读者准备了一份特殊的神秘礼物…… 在分享【特殊礼物】之前,请允许我分享一下《线下营销与线上销售的9大核心差异》…… 1、注意力; 2、销…

nginx--反向代理

反向代理 指的是代理外网用户的请求到内部的指定web服务器器,并将数据返回给用户的一种方式,这是用的比较多的一种方式 模块和功能 ngx_http_proxy_module: 将客户端的请求以http协议转发至指定服务器进行处理。ngx_stream_proxy_module&…

我从这些书籍中学来的财务以及税务知识

“你不能指望在开始工作的头两年攒下任何积蓄。” 这句话一直是我的座右铭,也是我给大学生的个人理财建议。这也就难怪我二十出头的时候,基本就是靠薪水过日子。 回想起来,我意识到其实这并不是最好的建议,甚至非常不好。 我现…

MySQL卸载

目录 MySQL卸载 1.关闭服务 2.卸载软件 3.清理文件夹 4.清理注册表 5.重启电脑 说明 上一篇文章介绍了数据库的一些基本概念,以及MySQL的数据模型,并在文章末尾附上了MySQL的下载地址,但是对于已经安装过MySQL的同学,如果需…

【小菜鸟之---Ansible基础详解】

文章目录 1 【Ansible简介】1.1简介1.2 Ansible 特点1.3 Ansible的工作机制1.4Ansible任务工作模式 2【安装部署】2.1安装命令2.2 Ansible配置文件2.3主机清单配置2.4 基于ssh免密登录2.5常用命令 3【Ansible常用模块】3.1 ping模块3.2 shell模块3.3 command模块3.4 copy模块3.…