网络模型图:应用层,传输层,网络层,链路层
什么是Socket?
Socket就是为网络服务提供的一种机制。
通讯的两端都有Sokcet
网络通讯其实就是Sokcet间的通讯
数据在两个Sokcet间通过IO传输。
TCP与UDP在概念上的区别:
udp: a、是面向无连接, 将数据及源的封装成数据包中,不需要建立连接
b、每个数据报的大小在限制64k内
c、因无连接,是不可靠协议
d、不需要建立连接,速度快
tcp: a、建议连接,形成传输数据的通道.
b、在连接中进行大数据量传输,以字节流方式
c 通过三次握手完成连接,是可靠协议
d 必须建立连接m效率会稍低
UDP的客户端与服务端代码:
package com.example.demo.socket;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
/**
* @author:qsc
* @date: 2019/5/6
* @time: 18:09
* @Describe: 模拟udp 服务器,客户端
* 运行时先运行服务端,会一直阻塞,再运行客户端,观察控制台
* 如果先启动客户端也不会报错
*/
//服务器端
class UdpServer {
public static void main(String[] args) throws IOException {
//1.ip地址+端口号
System.out.println("Udp服务器已经启动...8080端口");
//创建服务器端口号,默认使用本机Ip地址
DatagramSocket dS=new DatagramSocket(8080);
//服务器接收客户端1024个字节
byte[] bytes=new byte[1024];
//定义数据包
DatagramPacket dp=new DatagramPacket(bytes,bytes.length);
//接收客户端请求,将数据接收给数据包 如果客户端不往服务器发生请求的话,就一直阻塞
dS.receive(dp);
System.out.println("来源ip地址:"+dp.getAddress()+"端口号:"+dp.getPort());
String result=new String (dp.getData(),0,dp.getLength());
System.out.println("服务器端接收到的数据"+result);
dS.close();
}
}
//先写服务器,再写客户端
public class UdpClient {
public static void main(String[] args) throws IOException {
System.out.println("udp客户端启动连接");
//不传入端口号,表示创建一个socket客户端
DatagramSocket ds=new DatagramSocket();
String str="客户端测试";
byte[] strBytes=str.getBytes();
DatagramPacket dp=new DatagramPacket(strBytes,strBytes.length, InetAddress.getByName("127.0.0.1"),8080);
ds.send(dp);
ds.close();
}
}
Tcp三次握手和四次挥手:
在TCP/IP协议中,TCP协议采用三次握手建立一个连接。
第一次握手:建立连接时,客户端发送SYN包(SYN=1)到服务器,并进入SYN_SEND状态,等待服务器确认;
第二次握手:服务器收到SYN包,必须确认客户的SYN(ACK=X+1),同时自己也发送一个SYN包(SYN=1),即SYN+ACK包,此时服务器V状态;
第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ACK=Seq+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。
完成三次握手,客户端与服务器开始传送数据,
4次:
由于TCP连接是全双工的,因此每个方向都必须单独进行关闭。这个原则是当一方完成它的数据发送任务后就能发送一个FIN来终止这个方向的连接。收到一个 FIN只意味着这一方向上没有数据流动,一个TCP连接在收到一个FIN后仍能发送数据。首先进行关闭的一方将执行主动关闭,而另一方执行被动关闭。
(1)客户端A发送一个FIN,用来关闭客户A到服务器B的数据传送。
(2)服务器B收到这个FIN,它发回一个ACK,确认序号为收到的序号加1。和SYN一样,一个FIN将占用一个序号。
(3)服务器B关闭与客户端A的连接,发送一个FIN给客户端A。
(4)客户端A发回ACK报文确认,并将确认序号设置为收到序号加1。
tcp服务器与客户端代码
package com.example.demo.socket;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
/**
* @author:qsc
* @date: 2019/5/7
* @time: 8:12
* @Describe: tcp服务端与客户端
*/
//服务端
class TcpServer{
public static void main(String[] args) throws IOException {
System.out.println("tcp启动");
//创建服务器连接
ServerSocket ss=new ServerSocket(8080);
//接收客户端请求,阻塞功能
java.net.Socket accept=ss.accept();
InputStream inputStream=accept.getInputStream();
//将字节流转换成String类型
byte[] bytes=new byte[1024];
int len=inputStream.read();
String result=new String(bytes,0,len);
System.out.println("服务器接收内容:"+result);
ss.close();
}
}
//客户端
public class TcpClient {
public static void main(String[] args) throws IOException{
System.out.println("socket tcp 客户端启动....");
Socket socket=new Socket("127.0.0.1",8080);
OutputStream outputStream = socket.getOutputStream();
outputStream.write("tcp请求服务器".getBytes());
socket.close();
}
}