前言
本文大致分为两个部分,首先先概述了一下网络编程中TCP和UDP二者的概念及区别,然后是分析了三次握手和四次挥手,主要是从这几个概念入手,希望大家看完这篇文章后,会加深之前的认识。
网络编程
TCP:传输控制协议(TCP,Transmission Control Protocol)是为了在不可靠的互联网络上提供可靠的端到端字节流而专门设计的一个传输协议。
TCP旨在适应支持多网络应用的分层协议层次结构。 连接到不同但互连的计算机通信网络的主计算机中的成对进程之间依靠TCP提供可靠的通信服务。TCP假设它可以从较低级别的协议获得简单的,可能不可靠的数据报服务。 原则上,TCP应该能够在从硬线连接到分组交换或电路交换网络的各种通信系统之上操作。
UDP:UDP是一个非连接的协议,传输数据之前源端和终端不建立连接, 当它想传送时就简单地去抓取来自应用程序的数据,并尽可能快地把它扔到网络上。 在发送端,UDP传送数据的速度仅仅是受应用程序生成数据的速度、 计算机的能力和传输带宽的限制; 在接收端,UDP把每个消息段放在队列中,应用程序每次从队列中读一个消息段。
TCP与UDP的区别:
1、基于连接与无连接;
2、对系统资源的要求(TCP较多,UDP少);
3、UDP程序结构较简单;
4、流模式与数据报模式 ;
5、TCP保证数据正确性,UDP可能丢包;
6、TCP保证数据顺序,UDP不保证。
三次握手四次挥手
三次握手(three-way handshaking)
1.背景:TCP位于传输层,作用是提供可靠的字节流服务,为了准确无误地将数据送达目的地,TCP协议采纳三次握手策略。
2.原理:
1)发送端首先发送一个带有SYN(synchronize)标志地数据包给接收方。
2)接收方接收后,回传一个带有SYN/ACK标志的数据包传递确认信息,表示我收到了。
3)最后,发送方再回传一个带有ACK标志的数据包,代表我知道了,表示’握手‘结束。
通俗的说法
1)Client:嘿,李四,是我,听到了吗?
2)Server:我听到了,你能听到我的吗?
3)Client:好的,我们互相都能听到对方的话,我们的通信可以开始了。
3次握手
四次挥手(Four-Way-Wavehand)
1.意义:当被动方收到主动方的FIN报文通知时,它仅仅表示主动方没有数据再发送给被动方了。但未必被动方所有的数据都完整的发送给了主动方,所以被动方不会马上关闭SOCKET,它可能还需要发送一些数据给主动方后,再发送FIN报文给主动方,告诉主动方同意关闭连接,所以这里的ACK报文和FIN报文多数情况下都是分开发送的。
2.原理:
1)第一次挥手:Client发送一个FIN,用来关闭Client到Server的数据传送,Client进入FIN_WAIT_1状态。
2)第二次挥手:Server收到FIN后,发送一个ACK给Client,确认序号为收到序号+1(与SYN相同,一个FIN占用一个序号),Server进入CLOSE_WAIT状态。
3)第三次挥手:Server发送一个FIN,用来关闭Server到Client的数据传送,Server进入LAST_ACK状态。
4)第四次挥手:Client收到FIN后,Client进入TIME_WAIT状态,接着发送一个ACK给Server,确认序号为收到序号+1,Server进入CLOSED状态,完成四次挥手
通俗的说法
1)Client:我所有东西都说完了
2)Server:我已经全部听到了,但是等等我,我还没说完
3)Server:好了,我已经说完了
4)Client:好的,那我们的通信结束l
四次挥手
一、测试IP
//测试IP
public class Dome01 {
public static void main(String[] args) {
try {
//返回百度主机IP
InetAddress byName1 = InetAddress.getByName("localhost");
InetAddress byName = InetAddress.getByName("127.0.0.1");
//返回自己主机IP
InetAddress localHost = InetAddress.getLocalHost();
System.out.println(byName);
System.out.println(localHost);
System.out.println(byName1);
System.out.println(byName1.getHostName());//获取域名或者自己电脑的名字
System.out.println(byName1.getHostAddress());//获取IDP
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
}
二、实现TCP聊天
//实现TCP聊天
//客户端
public class TCP02 {
public static void main(String[] args) {
Socket socket = null;
OutputStream outputStream = null;
try {
//获取服务器端口号
InetAddress byName1 = InetAddress.getLocalHost();
//获取服务端地址
int port =1234;
//创建一个Socket连接
socket = new Socket();
//发送消息IO流
outputStream = socket.getOutputStream();
outputStream.write("实现TCP聊天".getBytes());
} catch (Exception e) {
e.printStackTrace();
}finally {
//关闭
if (outputStream!=null){
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (socket!=null){
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
//实现TCP聊天
//服务端
public class TCP01 {
public static void main(String[] args) {
ServerSocket serverSocket = null;
Socket socket = null;
InputStream inputStream=null;
ByteArrayOutputStream byteArrayOutputStream=null;
try {
//设置地址
serverSocket = new ServerSocket(1234);
//等待客户端连接
socket = serverSocket.accept();
//读取客户端消息
inputStream = socket.getInputStream();
byteArrayOutputStream = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len;
while ((len=inputStream.read(buffer))!=-1){
byteArrayOutputStream.write(buffer,0,len);
}
System.out.println(byteArrayOutputStream.toString());
} catch (IOException e) {
e.printStackTrace();
}finally {
//关闭
if (byteArrayOutputStream!=null){
try {
byteArrayOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (inputStream!=null){
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (socket!=null){
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (serverSocket!=null){
try {
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
三、实现文件上传
先运行服务端,再运行客户端,否则报错连接不上吗,
package 网络编程.com.Dome;
import java.io.File;
import java.io.FileInputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
//客户端
public class TCP01 {
public static void main(String[] args) throws Exception {
//创建一个连接
Socket socket =new Socket(InetAddress.getByName("127.0.0.1"),9999);
//创建一个输出流
OutputStream outputStream= socket.getOutputStream();
//读取文件
FileInputStream fileInputStream = new FileInputStream(new File("E://JAVA文件/src/timg.jpg"));
//写出文件
byte[] bytes = new byte[1024];
int len;
while ((len = fileInputStream.read(bytes))!=-1){
outputStream.write(bytes,0,len);
}
//关闭资源
fileInputStream.close();
outputStream.close();
socket.close();
}
}
package 网络编程.com.Dome;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
//服务端
public class TCP02 {
public static void main(String[] args) throws Exception {
//创建服务
ServerSocket serverSocket = new ServerSocket(9999);
//监听客户端连接
Socket socket = serverSocket.accept();
//获取文件输入流
InputStream inputStream = socket.getInputStream();
//文件输出
FileOutputStream fileOutputStream = new FileOutputStream(new File("t.jpg"));
byte[] bytes = new byte[1024];
int len;
while ((len = inputStream.read(bytes))!=-1){
fileOutputStream.write(bytes,0,len);
}
//关闭资源
fileOutputStream.close();
inputStream.close();
socket.close();
serverSocket.close();
}
}
四、UDP消息发送
数据发送端
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
public class UDP01 {
public static void main(String[] args) throws Exception {
//创建Socket
DatagramSocket socket = new DatagramSocket();
//建包
String msg = "服务器连接";
//客户端IP
InetAddress inetAddress = InetAddress.getByName("localhost");
//定义一个端口
int post = 9999;
//数据,数据的长度起始,要发送给谁
DatagramPacket packet = new DatagramPacket(msg.getBytes(),0,msg.length(),inetAddress,post);
//发送包
socket.send(packet);
//关闭
socket.close();
}
}
数据接收端
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
public class UDP02 {
public static void main(String[] args) throws Exception {
//开放端口
DatagramSocket socket = new DatagramSocket(9999);
//接收数据包
byte[] bytes = new byte[1024];
DatagramPacket packet = new DatagramPacket(bytes,0,bytes.length);
socket.receive(packet);//阻塞接收
System.out.println(packet.getAddress().getHostAddress());
System.out.println(new String(packet.getData(), 0, packet.getLength()));
//关闭
socket.close();
}
}
五、UDP实现聊天
发送端
package 网络编程.com.Dome;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
//UDP实现聊天
public class UDP03 {
public static void main(String[] args) throws Exception {
//准备一个端口
DatagramSocket socket = new DatagramSocket(9999);
//准备数据读取控制台
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
//循环输入
while (true){
String data = reader.readLine();
//字节流数组
byte[] bytes = data.getBytes();
DatagramPacket packet = new DatagramPacket(bytes, 0, data.length(), new InetSocketAddress("127.0.0.1", 6666));
socket.send(packet);
//当控制台输入bye时终止循环
if (data.equals("bye")){
break;
}
}
socket.close();
}
}
接收端
package 网络编程.com.Dome;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
public class UDP04 {
public static void main(String[] args) throws Exception {
DatagramSocket socket = new DatagramSocket(6666);
while (true){
//准备接收
byte[] bytes = new byte[1024];
DatagramPacket packet = new DatagramPacket(bytes, 0, bytes.length);
socket.receive(packet);//阻塞式接收包裹
//断开连接
byte[] data = packet.getData();
String s = new String(data, 0, data.length);
System.out.println(s);
//当接收到bye关闭
if (s.equals("bye")){
break;
}
}
socket.close();
}
}
结尾
本文到这里就结束了,感谢大家看到最后,喜欢的朋友记得点赞加关注哦,如有不对之处还请多多指正。
网友评论