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

【Java】TCP网络编程(字节/符流)

在这里插入图片描述

文章目录

  • 概念
  • TCP网络编程
  • ServerSocket
  • socket
  • 使用区别和原理演示

概念

TCP(传输控制协议)是一种面向连接的协议,用于在计算机网络中可靠地传输数据。TCP是Internet协议族中的一个核心协议,它在传输层提供可靠、有序、基于流的传输服务。

网络编程是使用计算机网络进行编程的过程,可以使用各种编程语言和协议来实现网络通信。TCP网络编程是指使用TCP协议进行网络通信的编程技术。

TCP网络编程

TCP网络编程有两种模式,一种是服务器模式,另一种是客户端模式。服务器模式创建一个服务程序,等待客户端用户的连接,接收到用户的连接请求后,根据用户的请求进行处理;客户端模式则根据目的服务器的地址和端口进行连接,向服务器发送请求并对服务器的响应进行数据处理。

ServerSocket类和socket类(服务端/客户端)实现了基于TCP协议网络程序


客户端程序发起连接,形成数据通道,发给信息给服务端;服务器端在某个端口进行监听(这里以9999端口作为演示),当客户端连接到服务端后,实际上客户端是通过一个端口和服务端进行通讯的,这个端口是TCP/IP分配的(服务端通信的端口是固定的)

服务端
1.在本机的9999端口监听,等待连接
2.当没有客户端连接9999端口时,程序会阻塞,等待连接
3.通过socket.getInputStream()方法来读取客户端写入到通道的数据
客户端
1.连接服务端(IP,端口)
2.连接上后,会生成Socket,通过socket.getOutputStream()
3.通过输出流,写入数据到数据通道

ServerSocket

在客户/服务器通信模式中,服务器端需要创建监听特定端口的ServerSocket,ServerSocket负责接收客户连接请求。(用于监听端口)

该类提供了四个构造器,根据不同的场景进行选择
在这里插入图片描述
常用方法

  • accept():侦听并接受此套接字的连接;当有客户端连接的时候会返回一个Socket对象。此方法在连接传入之前一直阻塞

此代码执行之后,只会输出服务端在9999端口监听等待连接,而后一直阻塞等待(只有返回socket对象之后才会继续)

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;public class SocketTCP01Server {public static void main(String[] args) {try {ServerSocket serverSocket = new ServerSocket(9999);System.out.println("服务端在9999端口监听等待连接");Socket socket = serverSocket.accept();System.out.println("服务器端:"+socket.getClass());} catch (IOException e) {e.printStackTrace();}}
}

注意:要求被监听的端口没有被其他服务或程序占用,否则会出异常

socket

这个类实现了客户端套接字(也被称为“套接字”)。套接字是两台机器之间的通信的一个端点。 用于客户端与服务端之间的连接,如果连接成功返回Socket对象

该类提供了9个构造器,根据不同的场景进行选择
在这里插入图片描述
这里使用常用的Socket(InetAddress address, int port) 作为演示

  • address:IP地址
  • port:端口号

常用方法

  • getInputStream():返回socket的输入流,用于接收数据
  • getOutputStream:返回socket的输出流,用于发送数据
  • shutdownOutput():表示一个Output结束标记,表示后面没有要输入的东西
  • shutdownInput():表示一个Input结束标记,表示后面没有要读的数据了

通常Socket构造器中的IP地址写的是远程服务器的IP地址,这里作为演示使用本机IP

InetAddress.getLocalHost();//获取本机IP

此时先执行ServerSocket中监听指定端口(代码在ServerSocket中),然后执行下列代码,会连接成功

import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;public class SocketTCP01Client {public static void main(String[] args) {try {//连接本机的9999端口Socket socket = new Socket(InetAddress.getLocalHost(),9999);System.out.println("客户端:连接成功"+socket.getClass());} catch (IOException e) {e.printStackTrace();}}
}

客户端和服务端各有一个Socket对象

使用区别和原理演示

区别
当serverSocket.accept()时,可以返回多个socket对象(多并发)一台计算机可以同时提供多个服务,这些不同的服务之间通过端口号来区别,不同的端口号上提供不同的服务。当多个服务(服务器)连接同一个端口时,accept之后会返回多个socket对象

工作原理

  1. 服务端:监听端口,等待连接
  2. 客户端:连接服务端端口,返回Socket对象,同时服务端也返回Socket对象
  3. 客户端:连接上后,通过socket.getOutputStream()得到socket对象关联的输出流对象
  4. 客户端:通过输出流,写入数据
  5. 服务端:通过socket.getInputStream()读取客户端写入到数据通道的数据,并输出
  6. 客户端和服务端:socket和流进行关闭(close),避免造成资源浪费

代码演示
理论上服务端和客户端的程序应该是在不同的机器上的,这里为了方便,使用了一台机器(可以自行设置虚拟机)

1.客户端连接到服务端,发送hello server并退出;服务端接收到客户端的信息,打印并退出

以下代码执行过后,服务端会输出客户端发来的信息,先执行服务端,在执行客户端。如果出现异常,可以把电脑防火墙关闭

这里使用的String类中getBytes方法(字符串转字节数组)和String的构造器
在这里插入图片描述

服务端

import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;public class SocketTCP01Server {public static void main(String[] args) {InputStream inputStream = null;Socket socket = null;try {ServerSocket serverSocket = new ServerSocket(9999);System.out.println("服务端在9999端口监听等待连接");socket = serverSocket.accept();inputStream = socket.getInputStream();byte[] bytes = new byte[1024];int len =0;while ((len=inputStream.read(bytes))!=-1){System.out.println(new String(bytes,0,len));}} catch (IOException e) {e.printStackTrace();}finally {try {socket.close();inputStream.close();} catch (IOException e) {e.printStackTrace();}}}
}

客户端

import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;public class SocketTCP01Client {public static void main(String[] args) {Socket socket = null;OutputStream outputStream = null;try {socket = new Socket(InetAddress.getLocalHost(),9999);System.out.println("客户端:连接成功"+socket.getClass());outputStream = socket.getOutputStream();outputStream.write("hello,server".getBytes());} catch (IOException e) {e.printStackTrace();}finally {try {socket.close();outputStream.close();} catch (IOException e) {e.printStackTrace();}}}
}

2.客户端连接到服务端,发送hello,server,并接收服务端回发的hello,client并退出;服务端接收到客户端的信息,输出并退出

注意:在发送完一个数据的时候,需要有一个结束标记,表示该数据发送完毕,可以发送下一个,要不然当多个数据发送时,会出现死锁的情况。

服务端

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;public class SocketTCP02Server {public static void main(String[] args) {ServerSocket serverSocket = null;InputStream inputStream = null;Socket socket = null;OutputStream outputStream = null;try {serverSocket = new ServerSocket(9999);System.out.println("服务端在9999端口监听等待连接");socket = serverSocket.accept();inputStream = socket.getInputStream();byte[] bytes = new byte[1024];int len = 0;System.out.println("客户端发的信息为:");while ((len = inputStream.read(bytes)) != -1) {System.out.println(new String(bytes, 0, len));}socket.shutdownInput();//表示一个结束标记outputStream = socket.getOutputStream();outputStream.write("hello,client".getBytes());} catch (IOException e) {e.printStackTrace();} finally {try {socket.close();inputStream.close();outputStream.close();serverSocket.close();} catch (IOException e) {e.printStackTrace();}}}
}

客户端

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;public class SocketTCP02Client {public static void main(String[] args) {Socket socket = null;OutputStream outputStream = null;InputStream inputStream = null;try {socket = new Socket(InetAddress.getLocalHost(),9999);System.out.println("客户端:连接成功"+socket.getClass());outputStream = socket.getOutputStream();outputStream.write("hello,server".getBytes());socket.shutdownOutput();//表示一个结束标记inputStream = socket.getInputStream();byte[] buf = new byte[1024];int readlen = 0;System.out.println("服务端发的信息为:");while ((readlen = inputStream.read(buf))!=-1){System.out.println(new String(buf,0,readlen));}} catch (IOException e) {e.printStackTrace();}finally {try {socket.close();outputStream.close();inputStream.close();System.out.println("客户端退出");} catch (IOException e) {e.printStackTrace();}}}
}

3.使用TCP字符流完成网络数据通讯演示(这里使用了转换流,把字节流转换为字符流),如果使用字符流需要手动刷新,调用flush方法,否则数据不会写入

注意:newLine()也可以是设置写入标记(换行符),需要对方使用readLine():读取结束标记才可以

服务端

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;public class SocketTCP03Server {public static void main(String[] args) {ServerSocket serverSocket = null;InputStream inputStream = null;Socket socket = null;OutputStream outputStream = null;BufferedWriter bufferedWriter = null;try {serverSocket = new ServerSocket(9999);System.out.println("服务端在9999端口监听等待连接");socket = serverSocket.accept();inputStream = socket.getInputStream();BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));System.out.println(bufferedReader.readLine());
//            socket.shutdownInput();//表示一个结束标记outputStream = socket.getOutputStream();bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream));bufferedWriter.write("hello,client字符流");bufferedWriter.newLine();//结束标记bufferedWriter.flush();} catch (IOException e) {e.printStackTrace();} finally {try {socket.close();serverSocket.close();bufferedWriter.close();//关闭外层流即可} catch (IOException e) {e.printStackTrace();}}}
}

客户端

import java.io.*;
import java.net.InetAddress;
import java.net.Socket;public class SocketTCP03Client {public static void main(String[] args) {Socket socket = null;OutputStream outputStream = null;InputStream inputStream= null;BufferedReader bufferedReader = null;try {socket = new Socket(InetAddress.getLocalHost(),9999);System.out.println("客户端:连接成功"+socket.getClass());outputStream = socket.getOutputStream();BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream));bufferedWriter.write("hello,server字符流");bufferedWriter.newLine();//换行符,在这里表示结束标记bufferedWriter.flush();
//            socket.shutdownOutput();//表示一个结束标记inputStream = socket.getInputStream();bufferedReader = new BufferedReader(new InputStreamReader(inputStream));System.out.println(bufferedReader.readLine());} catch (IOException e) {e.printStackTrace();}finally {try {socket.close();bufferedReader.close();} catch (IOException e) {e.printStackTrace();}}}
}

相关文章:

【Java】TCP网络编程(字节/符流)

文章目录概念TCP网络编程ServerSocketsocket使用区别和原理演示概念 TCP(传输控制协议)是一种面向连接的协议,用于在计算机网络中可靠地传输数据。TCP是Internet协议族中的一个核心协议,它在传输层提供可靠、有序、基于流的传输服…...

Linux之init.d、rc.d文件夹说明

备注:Ubuntu没有rc.d文件夹,原因看问题四 Linux的几个重要文件 rc.d,init.d文件夹的说明 今天在研究mysql的安装的时候,最后一步要创建一个软连接,使得mysql服务可以自启动,代码如下: ln -s…...

数据结构与算法(六):图结构

图是一种比线性表和树更复杂的数据结构,在图中,结点之间的关系是任意的,任意两个数据元素之间都可能相关。图是一种多对多的数据结构。 一、基本概念 图(Graph)是由顶点的有穷非空集合和顶点之间边的集合组成&#x…...

Kubernetes07:Service

Kubernetes07:Service 1、service存在的意义 因为Pod的IP是不断变化的,所以需要注册service防止pod失联 1)为了防止Pod失联(服务发现) 2、定义一组Pod访问策略(负载均衡) 2、Pod和Service的关系-------通…...

Qt音视频开发18-不同视频打开无缝切换

一、前言 在轮询视频的时候,通常都是需要将之前的视频全部关闭,然后打开下一组视频,在这个切换的过程中,如果是按照常规的做法,比如先关闭再打开新的视频,肯定会出现空白黑屏之类的过度空白区间&#xff0…...

智能驾驶词典 --- 自动驾驶芯片梳理

0 前言 与智能驾驶相关的芯片主要分为自动驾驶芯片(边缘端)和智能座舱芯片两大类,另外衍生的相关芯片种类还有计算集群芯片(云端), 1 自动驾驶芯片梳理 目前业内具有代表性的智驾芯片产品梳理如下。 1…...

在NVIDIA NX 配置OpenCV多版本冲突和解决的总结

Nvidia Jetson NX 环境 直接刷JetPack5.1的镜像,会得到如下环境 Ubuntu20.04cuda11.4TensorRT8.4cudnn8.4opencv4.5.4 而且这些源一般是从nv-xxxx等源下载的,打开软件Software&Update可以更该是否从这些源安装deb包。同时意味着,我们…...

记录pytorch安装 windows10 64位--(可选)安装paddleseg

安装完paddlepaddle之后,就可以安装paddleseg了。一、安装Git可以参考这个网址:https://blog.csdn.net/u010348546/article/details/124280236windows下安装git和gitbash安装教程二、安装paddleseghttps://github.com/PaddlePaddle/PaddleSeg记得翻墙啊这…...

UWB到底是什么技术?

什么是空间感知能力 所谓的空间感知能力,就是感知方位的能力。更直接一点,就是定位能力。说白了,利用UWB技术,手机和智能设备可以更精准地实现室内定位,不仅可以感知自己的位置,还可以感知周边其它手机或设…...

NCRE计算机等级考试Python真题(八)

第八套试题1、数据库设计中反映用户对数据要求的模式是___________。A.概念模式B.内模式C.设计模式D.外模式正确答案: D2、一个工作人员可使用多台计算机,而一台计算机被多个人使用,则实体工作人员与实体计算机之间的联系是___________。A.多…...

STM32之中断和事件

中断和事件什么是中断当CPU正在执行程序时,由于发生了某种事件,要求CPU暂时中断当前的程序执行,转而去处理这个随机事件,处理完以后,再回到原来被中断的地方,继续原来的程序执行,这样的过程称为…...

MySQL索引类型(type)分析

type索引类型 system > const > eq_ref > ref > range > index > all 优化级别从左往右递减,没有索引的⼀般为’all’。推荐优化目标:至少要达到 range 级别, 要求是 ref 级别, 如果可以是 const 最好&#xff…...

Linux | 2. 用户管理

如有错误,恳请指出。 1. 设置文件权限 权限设置如下: root表示文件所有者,stud1表示文件所属组。其他用户无法访问。更改指令是chown。 更改目录文件所属组:chown .lab lossfound/更改目录文件所有者:chown lab loss…...

【MySQL之SQL语法篇】系统学习MySQL,从应用SQL语法到底层知识讲解,这将是你见过最完成的知识体系

文章目录一、数据管理技术的三个阶段二、SQL语句学习1. DCL数据控制语言1.1 创建用户1.2 修改用户名1.3 修改密码1.4 删除用户1.5 授权1.6 查看权限1.7 回收权限2. DDL数据定义语言2.1 操作数据库2.2 操作数据表2.3 操作数据3. DQL数据查询语言基本语法3.1 单表查询3.1.1选择表…...

CentOS8基础篇7:Linux系统启动配置

一、Linux系统的启动过程 Linux的启动过程大体分为五个阶段: 1.计算机主机加电后,CPU初始化自身,接着在硬件固定位置执行一条指令。这条指令跳转到BIOS,BIOS找到启动设备并获取MBR,该MBR指向LILO或GRUB。 …...

vue中的$forceUpdate()、$set()

$forceUpdate() 迫使vue实例重新(rander)渲染虚拟dom,注意并不是重新加载组件。 结合vue的生命周期,调用 $forceupdate 后只会触发beforeupdate和updated这两个钩子函数,不会触发其他的钩子函数。它仅仅影响实例本身和…...

记住这3点,有效提高江苏专转本上岸率

记住这3点,有效提高上岸率 我们都知道,在江苏统招专转本考试中想岸并不是一件容易的事情。考生能否顺利上岸,往往受多方面因素影响,这其中包括:个人基础、学习方式、信息搜索能力。 如何提高自己的专转本上岸几率&…...

【经验总结】10年的嵌入式开发老手,到底是如何快速学习和使用RT-Thread的?(文末赠书5本)

【经验总结】一位近10年的嵌入式开发老手,到底是如何快速学习和使用RT-Thread的? RT-Thread绝对可以称得上国内优秀且排名靠前的操作系统,在嵌入式IoT领域一直享有盛名。近些年,物联网产业的大热,更是直接将RT-Thread这…...

人大金仓和达梦的空间数据能力对比

一、总得来说: 人大金仓底层更解决于pg数据库, 人大金仓的空间能力基于postgis能力来实现,能力挺强大的. 细节上人大金仓的架构上也对空间的支持框架做的比达梦更加完善。例如数据库的集群能力,并行计算能力,空间数据…...

探析集团企业 1+N 模式,重新定义集团型CRM

目录 一、客户经营、运营监控 二、流程驱动、业务成长 三、规则规范 业务治理 什么是集团型CRM【1N】?本文中我们可以把集团看作为“1”,其他分公司或组织看作为“N”。本篇我们主要分析集团CRM业务定位。 我们从企业集团总部的职能定位确定集团CRM…...

卡特兰数

文章目录1、简介1.1 何为卡特兰数1.2 卡特兰数的通项公式2、应用2.1 题目1:括号合法题目描述思路分析2.2 题目2:进出栈的方式2.2.1 题目描述2.2.2 思路分析2.3 题目3:合法的序列2.3.1 题目描述2.3.2 思路分析2.3.3 代码实现2.4 题目4&#xf…...

分布式任务处理

分布式任务处理 1. 什么是分布式任务调度 视频上传成功需要对视频的格式进行处理,如何用Java程序对视频进行处理呢?这里有一个关键的需求就是当视频比较多的时候我们如何可以高效处理。 如何去高效处理一批任务呢? 1、多线程 多线程是充…...

Linux 命令复习

常用命令 1、目录操作 cd 切换目录 cd / 切换到根目录 cd ~ 回到个人用户的主目录 ls 查看当前目录下所有文件的详细信息 list的意思 ll 查看当前目录下所有文件的详细信息 pwd 显示当前目录的全路径 . …...

leetcode 困难 —— 天际线问题(优先队列)

(思路感觉挺明显的,就是一些特殊情况得考虑清楚) 题目: 城市的 天际线 是从远处观看该城市中所有建筑物形成的轮廓的外部轮廓。给你所有建筑物的位置和高度,请返回 由这些建筑物形成的 天际线 。 每个建筑物的几何信息…...

离散数学笔记_第一章:逻辑和证明(2 )

1.2 命题逻辑的应用1.2.1 语句翻译 1.2.2 系统规范说明 1.2.3 布尔搜索 1.2.4 逻辑谜题泥巴孩子谜题骑士和流氓(考研逻辑题)1.1.2.5 逻辑电路1.2.1 语句翻译 🐳为啥要翻译语句? ➡因语言常常有二义性(有歧义&#x…...

MFCC语音特征值提取算法

博主简介 博主是一名大二学生,主攻人工智能研究。感谢让我们在CSDN相遇,博主致力于在这里分享关于人工智能,c,Python,爬虫等方面知识的分享。 如果有需要的小伙伴可以关注博主,博主会继续更新的&#xff0c…...

TencentOS3.1编译安装redis6.2.5

下载地址:https://redis.io/download 最近版为7.0.8,本次安装的是6.2.5 软件包解包并进入目录。 redis是c语言编写的,编译需要gcc,按网上资料说默认安装的gcc版本过低(可能是4.8.5),使用rpm …...

AI顶会accepted papers list

为方便相关paper调研,对相关顶会文章列表和下载地址汇总,会议包括:AAAI、ACL、IJCAI、ICLR、COLING、SIGIR、WSDM、WWW、ICML、KDD、NeurIPS、CVPR、ECCV、ACM MM 2023 Accepted papers list 更新于:(2022.11.24&…...

IOS逆向之frida安装

首先手机要越狱,这个就不说了,博主就是咸鱼搞了个160的苹果6, 自己刷到苹果6支持最新的12.5.7版本后越狱; 谁让他低版本,不支持 CrackerXI砸壳呢,当时你要是使用 frida-ios-dump 也是可以的; …...

《金山区提信心扩需求稳增长促发展行动方案》的通知

金发改规〔2023〕1号 各镇政府、街道办事处、园区管委会,区政府各部门、各直属单位: 《金山区提信心扩需求稳增长促发展行动方案》已经区委、区政府同意,现印发给你们,请认真按照执行。 附件:金山区提信心扩需求稳增…...

wordpress无法找到该页/百度推广登录入口

验证密码的位数并包含数字、字母和符号。 models.py from django.contrib.auth.models import AbstractUserclass User(AbstractUser):继承内置用户表...forms.py import refrom django import forms from django.contrib.auth import get_user_modelUser get_user_model()…...

合肥做网站公司哪家好/高端网站定制

之前博主已将讲过了使用链表对栈的这种结构的基本操作,同时也将数组对栈的基本操作的代码附上网址,以及对栈的应用已经提过。今天我们来看,使用链表对队列这种数据结构的操作 队列 队列:列是一种特殊的线性表,特殊之处…...

域名备案的网站名称/网站seo视频狼雨seo教程

一、前言 二、Web服务器提供服务的方式 三、多进程、多线程、异步模式的对比 四、Web服务请求过程 五、Linux I/O模型 六、Linux I/O模型具体说明 七、Linux I/O模型的具体实现 八、Apache的工作方式 九、支持高并发的web服务器 十、Nginx详解一、前言线程、进程、以及并发连接…...

政府类网站建设/爱站网官网查询域名

1、首先到oracle下载上下载jdk-7u5-linux-x64.tar.gz 2、将jdk-7u5-linux-x64.tar.gz拷贝到/usr/lib/jdk/目录下面,这里如果没有jdk文件夹,则创建该文件夹,命令: sudo mkdir jdk //创建文件夹jdk sudo cp -r ~/download/jdk-7u5-linux-x64.tar.gz /u…...

南京移动网站建设/网店推广方式

8.1.4路由表<?xml:namespace prefix o ns "urn:schemas-microsoft-com:office:office" />1、目的类型网络\路由器网络条目&#xff1a;数据包所要转发的目的网络地址路由器条目&#xff1a;到达ABR和ASBR路由器的路由Show ip routeShow ip ospf border-rout…...

义乌城市投资建设集团网站/上海网站推广广告

2019独角兽企业重金招聘Python工程师标准>>> 使用3枚币值分别为 1、3、4的硬币兑换11&#xff0c;最少需要几枚硬币。注意此题属于恰好装满的情况&#xff0c;需注意初始化&#xff0c;数组F&#xff08;0&#xff09;为0&#xff0c;其余的为正极大值或极小值&…...