java socket编程总结

article/2025/10/15 1:52:38

java socket编程总结

  • 说明
  • 一、TCP/IP协议模型
  • 二、获取IP相关信息
    • InetAddress
    • InetSocketAddress
    • URL
  • 三、TCP编程
  • 四、UDP编程
  • 五、关于TCP与UDP

说明

更新时间:2020/12/01 17:17,更新完基本内容

java的socket编程做一个总结,主要是面向Tcp和Udp编程

注意:本文仅为记录学习轨迹,如有侵权,联系删除

一、TCP/IP协议模型

在学习socket编程之前有必要复习一下TCP/IP协议模型,模型图片如下,注意,OSI是国际定义的协议,但是现在在用的协议是TCP/IP协议,所以重点学习TCP/IP协议
在这里插入图片描述

注意不同层之间所支持的协议,例如目前最常用的http协议等

java的socket编程,应用层采用http协议,传输层主要有TCP和UDP,网络层采用IP协议,至于链路层就不在考虑范围了,因为链路层是物理链路层面的东西,不是软件开发的层面。

注意,这里的socket编程主要是针对TCP和UDP这两个传输层协议进行的编程开发。

二、获取IP相关信息

在对TCP和UDP进行编程开发之前,先了解一下java对socket编程的支持,主要有两个类InetAddress和InetSocketAddress。

InetAddress

InetAddress是java.net包提供的用于网络编程的类,InetAddress可以获取对应ip或者对应域名的相关信息,例如ip信息和域名信息,但是没有端口号信息,如果要获取端口号信息,则需要用到下面要用到的InetSocketAddress类

public class InetAddressTest {/*** 获取本地主机ip信息*/static void getLocalhost(){try {//获取本地主机的相关信息InetAddress localHost = InetAddress.getLocalHost();//ipString hostAddress = localHost.getHostAddress();//主机名称String hostName = localHost.getHostName();System.out.println("hostAddress = " + hostAddress);System.out.println("hostName = " + hostName);} catch (UnknownHostException e) {e.printStackTrace();}}/*** 或者对应的ip信息,根据传入的ip或域名获取相关信息* @param address*/static void getAddress(String address){try {//获取对应ip的相关信息InetAddress inetAddress = InetAddress.getByName(address);//获取主机ipString hostAddress = inetAddress.getHostAddress();//获取主机名称String hostName = inetAddress.getHostName();System.out.println("hostAddress = " + hostAddress);System.out.println("hostName = " + hostName);} catch (UnknownHostException e) {e.printStackTrace();}}public static void main(String[] args) {//        getLocalhost();getAddress("www.baidu.com");}
}

InetSocketAddress

InetSocketAddress是java.net包提供的用于网络编程的类,InetSocketAddress包含端口,用于socket通信的,下面只是演示一下一些基本功能,还没有用到通信

public class InetSocketAddressTest {public static void main(String[] args) {try {//解析域名获取ip与主机信息InetAddress inetAddress = InetAddress.getByName("www.baidu.com");//端口号int port = 4321;//获取InetSocketAddress类,主要用于socket通信,下面只是演示一下一些基本功能,还没有用到通信InetSocketAddress socket = new InetSocketAddress(inetAddress, port);//获取主机域名/ipInetAddress address = socket.getAddress();//获取主机名称,也就是域名String hostString = socket.getHostString();//获取主机名称,也就是域名String hostName = socket.getHostName();//获取端口号int port1 = socket.getPort();System.out.println("address = " + address);System.out.println("hostString = " + hostString);System.out.println("port1 = " + port1);System.out.println("hostName = " + hostName);} catch (UnknownHostException e) {e.printStackTrace();}}
}

URL

这个也是java.net包里面提供的一个类,它可以通过传入的url解析里面的所有的所有url相关的信息,例如:ip、主机域名、uri、端口号等

public class UrlTest {public static void main(String[] args) throws IOException {String urlStr = "https://www.csdn.net/nav/java?spm=1000.2115.3001.4125";URL url = new URL(urlStr);//用到的应用层协议String protocol = url.getProtocol();//主机名称,也就是域名String host = url.getHost();//端口号,如果url没有显示的添加有端口号则返回-1,注意与url.getDefaultPort()q区分开来int port1 = url.getPort();//端口号,会自动获取默认端口号int port2 = url.getDefaultPort();//资源路径String path = url.getPath();//请求参数,get才有String query = url.getQuery();//获取uriString uri = url.getFile();System.out.println("urlStr = " + urlStr);System.out.println("url.getProtocol() = " + url.getProtocol());System.out.println("url.getHost() = " + url.getHost());System.out.println("url.getPort() = " + url.getPort());System.out.println("url.getDefaultPort() = " + url.getDefaultPort());System.out.println("url.getPath() = " + url.getPath());System.out.println("url.getQuery() = " + url.getQuery());System.out.println("url.getRef() = " + url.getRef());System.out.println("url.getAuthority() = " + url.getAuthority());System.out.println("url.getContent() = " + url.getContent());System.out.println("url.getFile() = " + url.getFile());}}

三、TCP编程

前面说过,java的socket编程主要是在传输层进行编程,即传输层的TCP和UDP协议,利用jdk提供的类进行编程,下面实现一个利用TCP协议的客户端与服务端两端通信的例子。

注意:TCP只能实现一对一的通讯,因为TCP的性质决定的,在java中的实现步骤如下

  1. 服务端或客户端通过Socke或者ServerSocket创建一个socket
  2. 两端之间通信采用流的方式,通过socket.get的方式可以得到一个输入流和输出流
  3. 各个端之间的信息接收与发送都是用建立的输出流或输入流进行接收与发送
  4. 最后记得关闭资源即可

客户端代码Client

public class Client {public static void main(String[] args) {Socket socket = null;try {//主机ipString host = "127.0.0.1";//主机端口号int port = 8888;//创建套接字,套接字是传输层Tcp像应用层Http开的一个编程接口,开发人员主要是通过套接字对tcp进行编程socket = new Socket(host,8888);//向服务端发起一个请求,通过socket创建io输出流OutputStream outputStream = socket.getOutputStream();//通过io输出流创建数据输出流DataOutputStream dataOutputStream = new DataOutputStream(outputStream);//发起请求,这里直接传了一个hello过去dataOutputStream.writeUTF("这里是客户端,收到请回复");//通过socket创建io输入流InputStream inputStream = socket.getInputStream();//通过io输入流创建数据输入流DataInputStream dataInputStream = new DataInputStream(inputStream);//接收服务端的响应String s = dataInputStream.readUTF();System.out.println("客户端接收到的数据:[ " + s + " ]");//关闭数据传输流dataOutputStream.close();dataInputStream.close();} catch (IOException e) {e.printStackTrace();}}
}

服务端Server

public class Server {public static void main(String[] args) {int port = 8888;try {//创建一个ServerSocket,负责服务端这边监听对应端口号ServerSocket serverSocket = new ServerSocket(port);//接收客户端的请求,在没接收到请求会一直处于监听的状态Socket socket = serverSocket.accept();//处理客户端的请求,通过socket创建io输入流InputStream inputStream = socket.getInputStream();//通过io输入流创建数据传输流DataInputStream dataInputStream = new DataInputStream(inputStream);//获取请求数据String s = dataInputStream.readUTF();System.out.println("服务端接收到的数据:[ " + s+" ]");//给客户端回写数据OutputStream outputStream = socket.getOutputStream();DataOutputStream dataOutputStream = new DataOutputStream(outputStream);//给客户端响应数据dataOutputStream.writeUTF("这里是服务端,已收到客户端的请求的数据");//关闭资源dataInputStream.close();dataOutputStream.close();} catch (IOException e) {e.printStackTrace();}}
}

四、UDP编程

UDP跟TCP差别挺大的,TCP通信前需要进行3次握手,而且是面向连接的,只能一对一的通信,通过流的方式进行数据的接收与发送,UDP是无连接的协议,通信通过数据包的方式,不要经过3次握手,直接就发送出去,简单但是有可能会出现丢包的情况,下面以两端通信为例

注意:这里的步骤跟TCP有很大的差异,具体如下

  1. 两端都有一个ip地址和端口号,而且两端都需要通过DatagramSocket类创建自己对应ip和端口号的socket类
  2. 发送数据的时候,需要指定对面的ip和端口号,接收数据的时候,自己的ip和端口号必须跟发送端的一致,这样才能接收到数据
  3. 关闭资源
  4. 可以看到,指定端口号与ip的方式跟TCP直接两端建立了一个流管道的方式通信有很大差异,而且udp的方式只要知道对方的ip跟端口号就可以通信,即可以实现一对多通信

客户端Client

public class Client {public static void main(String[] args) {try {//不知道端口号,默认随机分配DatagramSocket socket = new DatagramSocket();//封装数据并且发送数据String  str = "hello! 在没";byte[] bytes = str.getBytes();//获取要发送的服务端ip信息InetAddress add = InetAddress.getByName("127.0.0.1");int port = 8888;//封装成一个数据包DatagramPacket datagramPacket = new DatagramPacket(bytes, bytes.length, add, port);//发送数据包socket.send(datagramPacket);//关闭资源socket.close();} catch (SocketException e) {e.printStackTrace();} catch (UnknownHostException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}
}

服务端Server

public class Server {public static void main(String[] args) {try {//DatagramSocket:用于发送或接收数据包//注意:这里的端口号必须跟client的发送过来的端口号一致,表示只接收这个端口号发过来的信息DatagramSocket socket = new DatagramSocket(8888);//创建字节数组,存放数据包数据byte[] buff = new byte[1024];//创建一个数据包DatagramPacket datagramPacket = new DatagramPacket(buff, buff.length);//将接收的数据放到数据包中socket.receive(datagramPacket);//将数据转为字符串输出String s = new String(datagramPacket.getData(), 0, datagramPacket.getLength());System.out.println("s = " + s);//关闭资源socket.close();} catch (SocketException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}
}

五、关于TCP与UDP

UDPTCP
是否连接无连接面向连接
是否可靠不可靠传输,不使用流量控制和拥塞控制可靠传输,使用流量控制和拥塞控制
连接对象个数支持一对一,一对多,多对一和多对多交互通信只能是一对一通信
传输方式面向报文面向字节流
首部开销首部开销小,仅8字节首部最小20字节,最大60字节
适用场景适用于实时应用(IP电话、视频会议、直播等)适用于要求可靠传输的应用,例如文件传输

简述“3次握手”和“4次挥手”

第一次握手

  • 客户端向服务端发送连接请求报文段。该报文段中包含自身的数据通讯初始序号。请求发送后,客户端便进入 SYN-SENT 状态。

第二次握手

  • 服务端收到连接请求报文段后,如果同意连接,则会发送一个应答,该应答中也会包含自身的数据通讯初始序号,发送完成后便进入 SYN-RECEIVED 状态。

第三次握手

  • 当客户端收到连接同意的应答后,还要向服务端发送一个确认报文。客户端发完这个报文段后便进入 ESTABLISHED 状态,服务端收到这个应答后也进入 ESTABLISHED 状态,此时连接建立成功。

四次挥手
第一次握手

  • 若客户端 A 认为数据发送完成,则它需要向服务端 B 发送连接释放请求。

第二次握手

  • B 收到连接释放请求后,会告诉应用层要释放 TCP 链接。然后会发送 ACK 包,并进入 CLOSE_WAIT 状态,此时表明 A 到 B 的连接已经释放,不再接收 A 发的数据了。但是因为 TCP 连接是双向的,所以 B 仍旧可以发送数据给 A。

第三次握手

  • B 如果此时还有没发完的数据会继续发送,完毕后会向 A 发送连接释放请求,然后 B 便进入 LAST-ACK 状态。

第四次握手

  • A 收到释放请求后,向 B 发送确认应答,此时 A 进入 TIME-WAIT 状态。该状态会持续 2MSL(最大段生存期,指报文段在网络中生存的时间,超时会被抛弃) 时间,若该时间段内没有 B 的重发请求的话,就进入 CLOSED 状态。当 B 收到确认应答后,也便进入 CLOSED 状态。

http://chatgpt.dhexx.cn/article/VcG6CYlt.shtml

相关文章

Java Socket网络编程,你要的实验,我都有

JAVA Socket编程 目录 JAVA Socket编程多人聊天室客户端源代码服务器端源代码运行展示 邮件发送客户端运行展示 在线云笔记客户端窗口服务器端代码运行展示 多人聊天室 客户端源代码 import java.awt.BorderLayout; import java.awt.HeadlessException; import java.awt.event…

【Java高级】初探socket编程 ——JavaSocket连接与简单通信

新学期生活开始一段时间了,要继续学习一些新的技术(这里指socket /doge),目标是尝试完成一个在线即时聊天的小程序(尽量不咕)。会更新一系列socket编程的技术文章,欢迎关注交流~ 那么千里之行&…

Java--Socket通信(双向,有界面)

服务端: import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.Toolkit; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStr…

JAVA 网络编程 Socket

网络:相互连接的计算机,带来的好处有共享资源,交换数据 IP地址:定位计算机地址 通常由网络地址主机地址组合 查看本机IP地址:电脑左下角输入CMD,回车在CMD界面输入ipconfig 127.0.0.1 测试本机网络配置 …

初识Java Socket编程

Java最初是作为网络编程语言出现的,其对网络提供了高度的支持,使得客户端和服务器的沟通变成了现实,而在网络编程中,使用最多的就是Socket。像大家熟悉的QQ、MSN都使用了Socket相关的技术。下面就让我们一起揭开Socket的神秘面纱。…

Java socket详解,看这一篇就够了

刚给大家讲解Java socket通信后,好多童鞋私信我,有好多地方不理解,看不明白。特抽时间整理一下,详细讲述Java socket通信原理和实现案例。整个过程楼主都是通过先简单明了的示例让大家了解整个基本原理,后慢慢接近生产…

递归下降文法C语言实验报告,递归下降分析法的简单例子的c语言实现

我们举的简单例子是 G[s]: S → a | ∧ | (T) T→T, S | S 转化为LL1文法 S →a |∧| (T) T →ST T→,ST| ε c语言代码实现 #include char scaner(char*input,int* p); void S(char*input,int* p); void T(char*input,int* p); void T1(char*input,int* p); void error(); int…

C++:编译实验之递归下降分析器

一、实验目的 1.加深对递归下降分析法一种自顶向下的语法分析方法的理解。 2.根据文法的产生式规则消除左递归,提取公共左因子构造出相应的递归下降分析器。 二、实验内容 根据课堂讲授的形式化算法,编制程序实现递归下降分析器,能对常见…

递归下降分析程序的设计和实现

递归下降分析程序的设计和实现 一、实验的目的和要求 1、了解语法分析的主要任务。 2、实现基本的递归下降分析器,能够分析任意的符号串是否为该文法所定义的合法算术表达式。二、实验环境 Windows7 Dev-C三、实验准备 先将递归下降分析程序的生成认真的学习一…

利用递归下降分析方法完成语法分析

一、 程序设计题目与说明 利用递归下降分析方法完成语法分析。 递归下降分析法是一种自顶向下的分析方法,文法的每个非终结符对应一个递归过程(函数)。分析过程就是从文法开始符出发执行一组递归过程(函数)&#xff…

编译原理 --- 递归下降分析器

第一部分 --- 构造递归下降分析器 1.在上面这个例子中则是子程序序A先调用子程序B,本程序结束完调用之后再返回来继续调用下一个符号 如果下一个符号是终结符的话那就直接进行匹配,不进行调用,匹配完后继续调用下一个符号 如果不是的话则调…

递归下降分析法实现强化计算器

一. 实验概述 1.使用bison 和 flex 实现扩展版计算器 该计算器支持实型的两种表达,分别是小数和科学计数法. 该计算器支持 加, 减, 乘 除 四种运算 和括号()运算符. 该计算器支持整形,实型混合运算 2.通过递归下降分析法自行编写的语法分析和使用flex进行的词法分析的计算器.…

编译原理研究性学习专题 2——递归下降语法分析设计原理与实现

1 实验内容 完成以下描述赋值语句的 LL(1)文法的递归下降分析程序 G[S]: S→ VE E→ TE’ E’→ ATE’ | e T→ FT’ T’→ MFT’ | E F→ (E) | i A→ | - M→ * | / V→ i 设计说明:终结符号 i 为用户定义的简单变量,即标识符的定义。 2 实验要求 …

Python技法之简单递归下降Parser的实现方法

文章目录 一. 算术运算表达式求值二. 生成表达式树三、左递归和运算符优先级陷阱四. 相关包 一. 算术运算表达式求值 对于简单的算术运算表达式,假定我们已经用分词技术将其转化为输入的tokens流,如NUMNUM*NUM。 在此基础上,我们定义BNF规则…

编译实验 . 递归下降分析器

实验目的: 1.1掌握语法分析方法。 1.2掌握使用算符优先分析法。 1.3完成语法分析程序的设计和实现。 1.4程序能完成对指定语言的语法分析。 2. 递归下降分析器 在不含左递归和每个非终结符的所有候选终结首符集都两两不相交的条件下,我们就可能构造…

用c语言编译递归下降翻译器,Java实现C语言语义分析(递归下降)

说起这次的语义分析,不得不说的是我的重大的改变。上一次的语法分析是利用了预测分析法来实现的,经过多方考证,发现用预测分析法的语法分析器基础来实现语义分析的困难重重,例如在语法指导翻译的时候那个栈的变化和各种属性的传递…

递归下降分析法

介绍: 递归下降分析法是针对LL(1)文法的一种语法分析方法; 通过对文法的消除左递归,提取左公因子,对各个产生式和非终结符求first()和follow()集,通过first()和follow()集构造该文法的预测分析表,当这个预…

编译原理实验-递归下降语法分析

具体代码已放至Github(仅供参考): qxpBlog/Compiler_UESTC: 电子科技大学编译原理实验 (github.com) 具体实验过程如下: 一、实验目的、原理、内容及步骤: (1)目的:通过本实验加深…

编译原理实验--实验二 递归下降法判断算术表达式的正确性--Python实现

目录 一、实验目的和要求 二、实验内容 三、实验环境 四、实验步骤 1、语法分析所依据的文法; 2、给出消除左递归及提取左公因子的文法; 五、测试要求 六、实验步骤 1、语法分析所依据的文法 2、给出消除左递归及提取左公因子的文法&#xff1…

递归下降语法分析

一、实验目的 递归下降语法分析 二、实验题目 三、分析与设计 四、源代码 #include <iostream> #include <fstream> #include <cstring> #include <string> #include <conio.h> #define digit 1 // 1数字 #define op 2 // -*/()# #define Hh …