Socket说明

概念

socket

socket 通信是基于TCP/IP 网络层上的一种传送方式,我们通常把TCP和UDP称为传输层。

socket,又称套接字,是在不同的进程间进行网络通讯的一种协议、约定或者说是规范

socket编程,它更多的时候像是基于TCP/UDP等协议做的一层封装或者说抽象,是一套系统所提供的用于进行网络通信相关编程的接口

七层模型

在这里插入图片描述

socket属于应用层,socket的应用层协议是HTTP协议

socket 代表的是其中的5、6层,也就是会话层、表示层

  1. 会话层负责 建立客户端和服务端(一般称主动发起连接的一方为客户端,另一方为服务端)的连接
  2. 表示层负责数据格式的转化、加密解密等操作

socket是基于应用服务与TCP/IP通信之间的一个抽象,他将TCP/IP协议里面复杂的通信逻辑进行分装,对用户来说,只要通过一组简单的API就可以实现网络的连接

TPC/IP协议是传输层协议,主要解决数据 如何在网络中传输,而HTTP是应用层协议,主要解决如何包装数据

我们在传输数据时,可以只使用(传输层)TCP/IP协议,但是那样的话,如 果没有应用层,便无法识别数据内容,如果想要使传输的数据有意义,则必须使用到应用层协议,应用层协议有很多,比如HTTP、FTP、TELNET等,也 可以自己定义应用层协议。WEB使用HTTP协议作应用层协议,以封装HTTP文本信息,然后使用TCP/IP做传输层协议将它发到网络上

socket是对TCP/IP协议的封装,Socket本身并不是协议,而是一个调用接口(API),通过Socket,我们才能使用TCP/IP协议

socket编程基本流程

在这里插入图片描述

API

服务端使用ServerSocket绑定IP和端口,
使用Accept监听端口是否有客户端发送连接请求,一旦有客户端发送连接请求,服务端就回送连接信息,正式建立连接。

Server端和Client端都可以通过Send,Write等方法与对方通信。

创建服务端socket


// 初始化服务端socket并且绑定9999端口
ServerSocket serverSocket  =new ServerSocket(9999);
// 创建服务端socket 绑定端口
ServerSocket serverSocket = new ServerSocket();
//绑定ip
serverSocket = new ServerSocket(8088, 10, InetAddress.getByName("192.168.0.110"));

创建客户端连接

// 和服务器创建连接
Socket socket = new Socket("192.168.0.111", 8088);

服务器端的基本实现

public class TcpSocketServer {

  public static void main(String[] args) {
        try {
            // 创建服务端socket 绑定端口
            ServerSocket serverSocket = new ServerSocket();
            //绑定ip
            serverSocket = new ServerSocket(8088, 10, InetAddress.getByName("192.168.0.110"));
            // 创建客户端socket 用户下面接收客户端socket对象
            Socket socket = new Socket();
            System.out.println("等待客户端连接...");
            //循环监听等待客户端的连接
            while(true){
                // 监听客户端  没有接受到数据才会停在此处 接受到往下执行
                socket = serverSocket.accept();
               //发送内容实现线程的创建
                ServerThread thread = new ServerThread(socket);  
                thread.start();
                //获取客户端的ip
                InetAddress address=socket.getInetAddress();
                System.out.println("当前链接的客户端的IP:"+address.getHostAddress());
            }
        } catch (Exception e) {
            // TODO: handle exception
            e.printStackTrace();
        }
	}
    
}



线程方法:

public class ServerThread extends Thread{

    private Socket socket = null;

    public ServerThread(Socket socket) {

        this.socket = socket;
    }
    public void run() {
        InputStream is=null;
        InputStreamReader isr=null;
        BufferedReader br=null;
        OutputStream os=null;
        PrintWriter pw=null;
        try {
            is = socket.getInputStream();
            isr = new InputStreamReader(is);
            br = new BufferedReader(isr);
            String info = null;
            while((info=br.readLine())!=null){
                System.out.println("客户端:"+info);
            }
            //非关闭连接 仅关闭一方的发送状况
            socket.shutdownInput();
            os = socket.getOutputStream();
            pw = new PrintWriter(os);
            pw.write("服务器欢迎你1");
            pw.flush();
        } catch (Exception e) {
            // TODO: handle exception
        } finally{
            //关闭资源
            try {
                if(pw!=null)
                    pw.close();
                if(os!=null)
                    os.close();
                if(br!=null)
                    br.close();
                if(isr!=null)
                    isr.close();
                if(is!=null)
                    is.close();
                if(socket!=null)
                    socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}



客户端的基本实现

public class TcpSocketClient {
    public static void client() throws InterruptedException {
        try {
            // 和服务器创建连接
            Socket socket = new Socket("192.168.0.111", 8088);
            // 要发送给服务器的信息
            OutputStream os = socket.getOutputStream();
            PrintWriter pw = new PrintWriter(os);
            pw.write("状态已改变");
            //flush方法是用于将输出流缓冲的数据全部写到目的地。
            //所以一定要在关闭close之前进行flush处理,即使PrintWriter有自动的flush清空功能
            pw.flush();
            socket.shutdownOutput();
            // 从服务器接收的信息
            InputStream is = socket.getInputStream();
            BufferedReader br = new BufferedReader(new InputStreamReader(is));
            String info = null;
            while ((info = br.readLine()) != null) {
                System.out.println("我是客户端,服务器返回信息:" + info);
            }
            br.close();
            is.close();
            os.close();
            pw.close();
            socket.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}



可以去看这篇博客这篇博客,参考socket的实现

socket长连接

通常情况下,如果说到了socket长连接,他们一般特指TCP/IP连接协议,这个协议是面向连接的可靠的数据流服务,它可以维持长时间,持续的交换数据包。

因而我们所说的长连接便是基于这个协议实现的,同时socket又为我们实现了这个功能,因此,这个 连接协议的长时间维持,也被称为socket长连接

也可以这样理解:指在一个连接上可以连续发送多个数据包,在连接保持期间,如果没有数据包发送,需要双方发链路检测包整个通讯过程,客户端和服务端只用一个Socket对象,长期保持Socket的连接

socket短连接

与长连接是长时间维持住连接以方便持续发送数据,但是很多时候我们并不需要长时间发送,我们只需要确认我们发送了,服务器处理了,就可以了。

所以,短连接就产生了,它是TCP/IP连接协议的使用完即关闭

短连接:连接服务是每次请求都建立链接,交互完之后关闭链接

我们的http协议便是基于此而来

长连接和短连接

在实际应用中,长连接他并不是真正意义上的长连接,他们是通过一种称之为心跳包或者叫做链路检测包,去定时检查socket 是否关闭,输入/输出流是否关闭

socket本身并不是一直通信协议,而是一套接口的封装。

而TCP/IP协议组里面的应用层包括FTP、HTTP、TELNET、SMTP、DNS等协议,

我们知道,http1.0是短连接,http1.1是长连接

在打开http通信协议里面在Response headers中可以看到这么一句Connection:keep-alive,就是表示长连接,但是他并不是一直保持的连接,他有一个时间段

如果想一直保持这个连接怎么办?

在制定的时间内让客户端和服务端进行一个请求,请求可以是服务端发起,也可以是客户端发起,通常我们是在客户端不定时的发送一个字节数据给服务端,这个就是我们称之为心跳包,想想心跳是为了检测人活着,心会定时的跳动,就是这个原理。


版权声明:本文为yyuggjggg原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。