【Java SE】网络编程
1. 网络编程概述
网络编程的目的:直接或者间接地通过网络协议与其他计算机实现数据交换,进行通讯。
网络编程两个主要的问题:
①如何精准地定位网络上的一台或多台主机,并定位主机上的特定应用
②找到主机后如何进行可靠高效的数据传输
1.1 网络通信要素
通信双方地址:
①IP地址(InetAddress):查找主机,对应问题一
唯一标识Internet上的计算机(通信实体)
本地回环地址(hostAddress):127.0.0.1 主机名(hostName):localhost
127.0.0.1,通常被称为本地回环地址(Loopback Address),不属于任何一个有类别地址类。它代表设备的本地虚拟接口,所以默认被看作是永远不会宕掉的接口。在Windows操作系统中也有相似的定义,所以通常在安装网卡前就可以ping通这个本地回环地址。一般都会用来检查本地网络协议、基本数据接口等是否正常的。
IP地址分类方式一:
IPv4:4个字节,4个0-255,以点分十进制表示,如192.168.1.1
IPv6:16个字节128位,写成8个无符号整数,每个整数用4个十六进制位表示,数之间用:分开
IP地址分类方式二:
公网地址(万维网使用)和私有地址(局域网使用)
InetAddress
| 实例化方法 | |
|---|---|
| getByName("") | 形参地址为IP或者域名 |
| getLoopbackAddress() | 本地回环地址的域名IP |
| getLocalHost() | 主机网络域名IP |
InetAddress inetAddress = InetAddress.getByName("192.168.10.14");
System.out.println(inetAddress);///192.168.10.14
InetAddress inetAddress1 = InetAddress.getByName("www.bilibili.com");
System.out.println(inetAddress1);//www.bilibili.com/120.92.78.97
InetAddress inetAddress2 = InetAddress.getLocalHost();
System.out.println(inetAddress2);//LAPTOP-B4BJHS06/192.168.137.1
InetAddress inetAddress3 = InetAddress.getLoopbackAddress();
System.out.println(inetAddress3);//localhost/127.0.0.1
| 实例方法 | |
|---|---|
| getHostName() | |
| getHostAddress() |
一定的规则,即网络通信协议:
①OSI参考模型(过于理想化)
②TCP/IP参考模型(或TCP/IP协议)

②端口号:标识主机上的应用程序,对应问题二
被规定为不同的16位整数0-65535
端口分类:
①公认端口:0-1023,被预定义的服务通信占用。如Http:80,FTP:21,Telnet:23
②注册端口:1024-49151,分配给用户进程和应用程序,如Tomcat:8080,MySQL:3306,Oracle:1521
③动态、私有端口:49152-65535
端口号与IP的组合为网络套接字:Socket
1.2 网络协议
也即是通信协议,对速率、传输代码、代码结构、传输控制步骤、出错控制等制定标准。同层之间可以通信、上一层可以调用下一层,而与再下一层不再发生关系。
1.2.1 TCP/IP协议簇
传输层包括TCP(传输层控制协议)和UDP(用户数据报协议)。
TCP协议:
使用TCP协议前,先建立TCP连接,形成数据传输通道;传输前,采用“三次握手”的方式,进行可靠的点对点通信;客户端和服务端两个应用进程在连接中进行大数据量的传输,传输结束需要释放已经建立的连接,效率低。


TCP网络编程示例:Socket和ServerSocket
@Test
public void client() {
InetAddress inet = null;
Socket socket = null;
OutputStream os = null;
try {
inet = InetAddress.getByName("10.42.138.5");
socket = new Socket(inet, 8899);
os = socket.getOutputStream();
os.write("人类荣光永存!".getBytes(StandardCharsets.UTF_8));
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if(socket != null)
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
if(os != null)
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
System.out.println(inet);
}
@Test
public void server() {
ServerSocket serverSocket = null;
Socket socket = null;
InputStream is = null;
while(true) {
try {
serverSocket = new ServerSocket(8899);
socket = serverSocket.accept();
is = socket.getInputStream();
// 方式一,数组长度不足会乱码,UTF汉字占两个字节
// int len;
// byte[] buffer = new byte[5];
// while((len = is.read(buffer)) != -1) {
// String str = new String(buffer);
// System.out.print(str);
// System.out.println();
// }
/*
人�
�荣�
��永
存�
����
*/
// 方式二:使用转换流将字节流转换为字符流
InputStreamReader isr = new InputStreamReader(is);
int len;
char[] chs = new char[1];
while ((len = isr.read(chs)) != -1) {
System.out.print(new String(chs, 0, len));
}
System.out.println();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (serverSocket != null) {
serverSocket.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if (socket != null) {
socket.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if (is != null) {
is.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
通过Socket传输图片
@Test
public void nib() {
FileInputStream fis = null;
Socket socket = null;
OutputStream outputStream = null;
try {
File file = new File(".\\data\\2B\\2b.jpg");
// System.out.println(file.getAbsolutePath());
fis = new FileInputStream(file);
InetAddress inetAddress = InetAddress.getByName("10.42.138.5");
socket = new Socket(inetAddress, 8899);
outputStream = socket.getOutputStream();
int len;
byte[] bytes = new byte[1024];
while((len=fis.read(bytes))!=-1) {
outputStream.write(bytes, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Test
public void kyuus() {
FileOutputStream fs = null;
ServerSocket serverSocket = null;
Socket socket = null;
InputStream is = null;
while(true) {
try {
serverSocket = new ServerSocket(8899);
socket = serverSocket.accept();
File file = new File(".\\data\\9S\\2b.jpg");
fs = new FileOutputStream(file);
is = socket.getInputStream();
int len;
byte[] bytes = new byte[1024];
while ((len = is.read(bytes)) != -1) {
fs.write(bytes, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fs.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
需要特别关注的是这一部分代码,file需要放在获取socket之后,否则会导致流无法写入
serverSocket = new ServerSocket(8899);
socket = serverSocket.accept();
File file = new File(".\\data\\9S\\2b.jpg");
fs = new FileOutputStream(file);
传输完成并回复消息:socket.shutdownOutput()
@Test
public void nib() {
FileInputStream fis = null;
Socket socket = null;
OutputStream outputStream = null;
try {
File file = new File(".\\data\\2B\\2b.jpg");
// System.out.println(file.getAbsolutePath());
fis = new FileInputStream(file);
InetAddress inetAddress = InetAddress.getByName("10.42.138.5");
socket = new Socket(inetAddress, 8899);
outputStream = socket.getOutputStream();
int len;
byte[] bytes = new byte[1024];
while((len=fis.read(bytes))!=-1) {
outputStream.write(bytes, 0, len);
}
socket.shutdownOutput();
InputStream is = socket.getInputStream();
byte[] bytes1 = new byte[1024];
while((len=is.read(bytes1))!=-1) {
System.out.println(new String(bytes1));
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Test
public void kyuus() {
FileOutputStream fs = null;
ServerSocket serverSocket = null;
Socket socket = null;
InputStream is = null;
while(true) {
try {
File file = new File(".\\data\\9S\\2b.jpg");
fs = new FileOutputStream(file);
serverSocket = new ServerSocket(8899);
socket = serverSocket.accept();
is = socket.getInputStream();
int len;
byte[] bytes = new byte[1024];
while ((len = is.read(bytes)) != -1) {
fs.write(bytes, 0, len);
}
is = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
char[] chs = new char[100];
while((len=isr.read(chs))!=-1) {
System.out.println(new String(chs,0,len));
}
OutputStream os = socket.getOutputStream();
os.write("传输完成".getBytes(StandardCharsets.UTF_8));
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fs.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
UDP协议:DatagramSocket和DatagramPacket
将数据、源、目的封装成数据报,不需要建立连接。每个数据包限制大小为64kb。由于不管对方是否准备好,接收方收到也不确认,因此是不可靠的。可以广播发送,发送数据结束时无序释放资源,开销小,速度快。适合传输一些视频。
UDP网络编程示例:
@Test
public void sender() {
DatagramSocket socket = null;
try {
InetAddress inet = InetAddress.getByName("localhost");
socket = new DatagramSocket();
byte[] data = "我是UDP发送方".getBytes(StandardCharsets.UTF_8);
DatagramPacket datagramPacket = new DatagramPacket(data, 0, data.length, inet, 8090);
socket.send(datagramPacket);
} catch (SocketException | UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
}
}
@Test
public void receiver() {
try {
InetAddress inet = InetAddress.getLocalHost();
DatagramSocket socket = new DatagramSocket(8090);
byte[] data = new byte[1024];
DatagramPacket datagramPacket = new DatagramPacket(data, 0, data.length);
socket.receive(datagramPacket);
System.out.println(new String(datagramPacket.getData(), 0, datagramPacket.getLength()));
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (SocketException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
}
}
UDP与TCP的不同:
TCP必须是服务器端先启动,否则客户端先发送握手请求,没有响应便会断开TCP连接,无法再进行数据传送。而UDP是无连接协议,发送方发送数据不需要判断接收方是否接收,接收方如果后启动就会接收不到数据,但仍然能继续传送数据。
IP协议是网络层的主要协议,支持网间互连的数据通信。
1.3 URL编程:统一资源定位符
| 常用方法 | |
|---|---|
| getProtocol() | 协议名称 |
| getPath() | 资源路径 |
| getHost() | 主机域名 |
| getPort() | 端口号 |
| getFile() | 资源文件 |
| getQuery() | 关键字序列 |
URL url = new URL("http://localhost:8080/examples/beauty.jpg?username='admin'&pwd='123");
System.out.println(url.getProtocol());
System.out.println(url.getPort());
System.out.println(url.getPath());
System.out.println(url.getHost());
System.out.println(url.getFile());
System.out.println(url.getQuery());
【Java SE】网络编程的更多相关文章
- 二十三、Java基础--------网络编程
Java中另一个重要技术就是网络编程了,为了更好的学习web方向的知识,有必要对java之网络编程好好学习,本文将围绕网络编程技术进行分析. 常见的网络协议:UDP.TCP UDP 1. 将数据源和目 ...
- JAVA的网络编程
网络编程 网络编程对于很多的初学者来说,都是很向往的一种编程技能,但是很多的初学者却因为很长一段时间无法进入网络编程的大门而放弃了对于该部分技术的学习. 在 学习网络编程以前,很多初学者可能觉得网络编 ...
- Java Socket 网络编程心跳设计概念
Java Socket 网络编程心跳设计概念 1.一般是用来判断对方(设备,进程或其它网元)是否正常动行,一 般采用定时发送简单的通讯包,如果在指定时间段内未收到对方响应,则判断对方已经当掉.用于 ...
- 20145325张梓靖 实验五 "JAVA的网络编程"
20145325张梓靖 实验五 "JAVA的网络编程" 实验内容 使用 JVAV语言 进行网络编程 对明文进行加密 设计过程 我完成的是客户端,服务端同伴 20145308刘昊阳 ...
- 【转】JAVA之网络编程
转自:火之光 网络编程 网络编程对于很多的初学者来说,都是很向往的一种编程技能,但是很多的初学者却因为很长一段时间无法进入网络编程的大门而放弃了对于该部分技术的学习. 在 学习网络编程以前,很多初学者 ...
- JAVA的网络编程【转】
JAVA的网络编程[转] Posted on 2009-12-03 18:04 火之光 阅读(93441) 评论(20) 编辑 收藏 网络编程 网络编程对于很多的初学者来说,都是很向往的一种编程技能, ...
- Java面向对象 网络编程 下
Java面向对象 网络编程 下 知识概要: (1)Tcp 练习 (2)客户端向服务端上传一个图片. (3) 请求登陆 (4)url 需求:上传图片. 客户端: ...
- Java面向对象 网络编程 上
Java面向对象 网络编程 上 知识概要: (1)网络模型 (2)网络通讯要素 (3)UDP TCP 概念 (4)Socket (5)UDP TCP 传输 ...
- Java基础——网络编程(二)
一.套接字 Socket 网络驱动程序提供给应用程序编程的接口和一种机制,可以比喻成一个港口码头 应用程序只要把货放在这,就算完成了货物的运送.它在应用程序中创建,通过一种绑定机制与驱动程序建立关系, ...
- java基础-网络编程(Socket)技术选型入门之NIO技术
java基础-网络编程(Socket)技术选型入门之NIO技术 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.传统的网络编程 1>.编写socket通信的MyServer ...
随机推荐
- springboot项目控制台日志不是彩色的原因
采用springboot的方式启动,而不是application的方式启动,即可
- linux 修改password
passwd 命令,手动修改: [root@localhost testuser]# passwd testuser Changing password for user testuser. New ...
- drf视图类
1 2个视图基类 # django 内置的View# drf 的APIView ,继承自View# GenericAPIView -两个重要的类属性: queryset = Book.objec ...
- 打开配置windos 2016 防火墙 日志
1 点击"开始"或者win+R打开"运行"对话框 键入gpedit.msc
- 利用fread读取二进制文件的bug
最近在做一个项目时需要读取二进制文件,我用C语言的fread进行读取,代码如下: FILE *fp; int read_data; fopen_s(&fp, file_path, " ...
- C#中静态字段声明时赋值与构造函数中赋值
C#中静态字段是属于类的,访问的时候:用类名点成员名的方式. 赋值初始化的时候,可以在声明的时候赋值,也可以在静态构造函数中赋值. 如果在声明中.静态构造函数中都赋值,那么最终该成员的值,是取自哪一个 ...
- php运行找不到命令
这个跟环境path设置有关: 1. 找php.ini位置./www/wdlinux/apache_php-5.5.38/bin 2. 写入默认path: export PATH=$PATH:/www/ ...
- Java下变量大小写驼峰、大小写下划线、大小写连线转换
<dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artif ...
- AttributeError: module 'torchvision' has no attribute 'transforms'
代码:maskrcnn-benchmark Python 3.6.13 |Anaconda, Inc Traceback (most recent call last): File "too ...
- springboot脱包部署
<plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactI ...