网络通信,UDP.TCP协议
网络通信
计算机网络
是指将地理位置不同的具有独立功能的多台计算机及其外部设备,通过通信线路连接起来,在网络操作系统,网络管理软件及网络通信协议的管理和协调下,实现资源共享和信息传递的计算机系统。
网络编程
就是用来实现网络互连的不同计算机上运行的程序间可以进行数据交换。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
网络通信三要素
IP地址:InetAddress
网络中设备的标识,不易记忆,可用主机名
端口号
用于标识进程的逻辑地址,不同进程的标识
传输协议
通讯的规则
常见协议:TCP,UDP
IP地址
要想让网络中的计算机能够互相通信,必须为每台计算机指定一个标识号,通过这个标识号来指定要接受数据的计算机和识别发送的计算机,在TCP/IP协议中,这个标识号就是IP地址。
// ip地址对象
// 不能通过构造方法创建
// 根据名字返回第一个所有符合要求的IP地址对象
InetAddress byName = InetAddress.getByName("PC201501241736");
//System.out.println(byName);
//这个方法也可以通过ip获取(将ip当做name填入)
//如果通过这种方式获取ip对象 那么不能获取计算机名
InetAddress byName2 = InetAddress.getByName("4B5MYUK5PQ2WSNI");
//System.out.println(byName2);
//返回指定ip对象代表 的计算机名
System.out.println(byName.getHostName());
//返回指定ip对象代表 的计算机IP地址
System.out.println(byName.getHostAddress());
端口号
物理端口 网卡口
逻辑端口 我们指的就是逻辑端口
A:每个网络程序都会至少有一个逻辑端口
B:用于标识进程的逻辑地址,不同进程的标识
C:有效端口:065535,其中01024系统使用或保留端口。
通过dom命令 netstat -ano可以查看所有占用的端口
通信协议
UDP
将数据源和目的封装成数据包中,不需要建立连接;每个数据报的大小在限制在64k;因无连接,是不可靠协议;不需要建立连接,速度快
数据报协议:将发送的数据分割为指定大小后发送,无需连接接受端,发送端只管发送数据,无论接收端是否接收都会发送
TCP
建立连接,形成传输数据的通道;在连接中进行大数据量传输;通过三次握手完成连接,是可靠协议;必须建立连接,效率会稍低
数据连接协议:数据的发送与接收建立在连接通道的基础上,客户端连接服务端后才可以发送接受请求数据
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
Socket
Socket套接字:
网络上具有唯一标识的IP地址和端口号组合在一起才能构成唯一能识别的标识符套接字。
Socket原理机制:
通信的两端都有Socket。
网络通信其实就是Socket间的通信。
数据在两个Socket间通过IO传输。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
使用UDP协议完成数据的发送与接收
发送端思路
1:建立udp的socket服务(创建DatagramSocket对象,发送端无需指定端口)
2:将要发送的数据封装成数据包(创建DatagramPacket对象,传入数据字节数组,数据长度,ip地址对象,接收方接收端口号,将数据格式化)
3:通过udp的socket服务,将数据包发送出(使用DatagramSocket对象的send方法发送数据包)
4:关闭资源(DatagramSocket对象的close方法)
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
//使用socket 与udp协议实现发送代码的书写
public class UdpSend {
public static void main(String[] args) throws IOException {
// 1:建立udp的socket服务
DatagramSocket ds = new DatagramSocket();
// 创建使用udp发送数据的socket对象 发送数据使用随机空闲端口
// DatagramSocket ds1 = new DatagramSocket(10000);
// 创建使用udp发送数据的socket对象 发送数据使用指定端口 若端口被占用会报错
// 2:将要发送的数据封装成数据包
// (1)准备要发送的数据(数据在网络传输本质字节流)
byte[] bytes = "udp发送数据".getBytes();
// (2)创建数据包对象 将数据进行格式化
DatagramPacket dp = new DatagramPacket(bytes, bytes.length, InetAddress.getByName("localhost"), 10000);
// 分别传入数据 数据长度 接受地址对象 接受端口号
// 3:通过udp的socket服务,将数据包发送出
ds.send(dp);
// 4:关闭资源
ds.close();
}
}
接收端思路
1:建立udp的socket服务(创建DatagramSocket对象,接收端需要根据发送端指定端口号)
2:创建接受数据包对象(创建Datagrampacket对象,传入每次接受字节数组以及字节数组长度)
3:通过receive方法接收数据,将收到的数据存储到数据包对象中(调用DatagramSocket对象receive阻塞方法传入Datagrampacket对象)
4:通过数据包对象的功能来完成对接收到数据进行解析.(获取发送方发送时传在数据包中定义的数据信息)
5:可以对资源进行关闭
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
//使用socket udp协议完成数据的接收
public class UdpReceipt {
public static void main(String[] args) throws IOException {
// 1:建立udp的socket服务
DatagramSocket ds = new DatagramSocket(10000);
// 2:通过receive方法接收数据
// (1)创建保存数据的数据包对象
byte[] b = new byte[1024];// 创建接受的字节数组
DatagramPacket dp = new DatagramPacket(b, b.length);
//使用字节数组接受数据并存储至数据包中
//(2)使用数据包对象接受数据
ds.receive(dp);
//receive是阻塞方法,与scanner的获取数据类似
//当程序执行到这个方法时会暂停运行,当接收到发送端发送的数据后继续执行
// 3:将收到的数据存储到数据包对象中
// 4:通过数据包对象的功能来完成对接收到数据进行解析.
InetAddress address = dp.getAddress();//获取请求地址对象
int port = dp.getPort();//获取请求端口
byte[] data = dp.getData();//获取存储数据的字节数组
int length = dp.getLength();//获取数据实际长度
System.out.println(address);
System.out.println(port);
System.out.println(new String(data, 0, length));
// 5:可以对资源进行关闭
ds.close();
}
}
使用UDP完成一对一信息的发送与接收
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.util.Scanner;
//使用udp协议完成客户端(既能发送也能接收)书写
public class UdpClient {
public static void main(String[] args) {
// 创建多个线程分别执行发送与接收
// 接收端线程
new Thread(new Runnable() {
@Override
public void run() {
// 创建udp协议接收端socket对象
try {
DatagramSocket ds = new DatagramSocket(10000);
// 创建接受数据的数据包对象
byte[] b = new byte[1024];
DatagramPacket dp = new DatagramPacket(b, b.length);
// 调用阻塞方法获取请求数据并使用数据包对象接收
while (true) {
ds.receive(dp);
// 从数据包对象中解析发送的数据
byte[] data = dp.getData();// 数据的字节数组
String hostAddress = dp.getAddress().getHostAddress();// 请求方ip
System.out.println(hostAddress + ":" + new String(data, 0, data.length));
}
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
// 发送到线程
new Thread(new Runnable() {
@Override
public void run() {
Scanner sc = new Scanner(System.in);
try {
// 创建发送端scocket对象
DatagramSocket ds = new DatagramSocket();
while (true) {
System.out.println("请输入 接收端ip:发送内容");
String str = sc.nextLine();
String[] split = str.split(":");
// 创建数据包对象并将数据字节数组传入
byte[] b = split[1].getBytes();
DatagramPacket dp = new DatagramPacket(b, b.length, InetAddress.getByName(split[0]), 10000);
// 将数据包对象发送至指定接收端
ds.send(dp);
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}).start();
}
}
使用TCP协议完成数据的发送与接收
接收端(服务器)思路
首先进行接收端的书写,tcp协议建立在连接之上,如果发送端没有连接到服务端则会报错
1:建立服务器端的socket服务(new ServerSocket(端口))
2:服务端没有直接流的操作,而是通过accept方法获取客户端对象,在通过获取到的客户端对象的流和客户端进行通信(获取连接服务器的客户端socket对象)
3:通过客户端的获取流对象的方法,读取数据或者写入数据(使用getinputStream方法获取输入流读取数据)
4:如果服务完成,需要关闭客户端,然后关闭服务器,但是,一般会关闭客户端,不会关闭服务器,因为服务端是一直提供服务的
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
//tcp服务器端(接收端)
public class TcpService {
public static void main(String[] args) throws Exception {
// 1:建立服务器端的socket服务,需要一个端口
ServerSocket ss = new ServerSocket(10000);
// 2:服务端没有直接流的操作,而是通过accept方法获取客户端对象,在通过获取到的客户端对象的流和客户端进行通信
Socket s = ss.accept();// 获取当前连接服务端的客户端对象
// 3:通过客户端的获取流对象的方法,读取数据或者写入数据
String hostAddress = s.getInetAddress().getHostAddress();
System.out.println(hostAddress + "连接服务器");
InputStream is = s.getInputStream();
byte[] b = new byte[1024];
int len = 0;
while ((len = is.read(b)) != -1) {
System.out.println(new String(b, 0, len));
}
// 4:如果服务完成,需要关闭客户端,然后关闭服务器,但是,一般会关闭客户端,不会关闭服务器,因为服务端是一直提供服务的
s.close();// 关闭客户端
ss.close();// 关闭服务器端
}
}
发送端(客户端)思路
发送端其实是将数据封装至发送端socket对象中,然后将socket对象发送至接收端进行接收
1:建立客户端的Socket服务,并明确要连接的服务器。(new)
2:如果连接建立成功,就表明,已经建立了数据传输的通道.就可以在该通道通过IO进行数据的读取和写入.该通道称为Socket流,Socket流中既有读取流,也有写入流.
3:通过Socket对象的方法,可以获取这两个流
4:通过流的对象可以对数据进行传输
5:如果传输数据完毕,关闭资源
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
//tcp客户端(发送端)
public class TcpClient {
public static void main(String[] args) throws Exception {
// 1:建立客户端的Socket服务,并明确要连接的服务器。
Socket s = new Socket("172.16.1.100", 10000);
// 2:如果连接建立成功,就表明,已经建立了数据传输的通道.就可以在该通道通过IO进行数据的读取和写入.该通道称为Socket流,Socket流中既有读取流,也有写入流.
// 3:通过Socket对象的方法,可以获取这两个流
OutputStream os = s.getOutputStream();
// 4:通过流的对象可以对数据进行传输
os.write("hello".getBytes());
// 5:如果传输数据完毕,关闭资源
os.flush();
os.close();
s.close();
}
}
转载:https://blog.csdn.net/shaonianayang/article/details/109751994