网络编程的目的:直接或者间接地通过网络协议与其他计算机实现数据交换,进行通讯。
网络编程两个主要的问题:
①如何精准地定位网络上的一台或多台主机,并定位主机上的特定应用
②找到主机后如何进行可靠高效的数据传输
通信双方地址:
①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
也即是通信协议,对速率、传输代码、代码结构、传输控制步骤、出错控制等制定标准。同层之间可以通信、上一层可以调用下一层,而与再下一层不再发生关系。
传输层包括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协议是网络层的主要协议,支持网间互连的数据通信。
常用方法
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());
手机扫一扫
移动阅读更方便
你可能感兴趣的文章