一、 socket概念

套接字(socket)是通信的基石,是支持TCP/IP协议的网络通信的基本操作单元。它是网络通信过程中端点的抽象表示,包含进行网络通信必须的五种信息:连接使用的协议,本地主机的IP地址,本地进程的协议端口,远地主机的IP地址,远地进程的协议端口。
一个Socket是一对IP地址和端口。
Socket可以看成在两个程序进行通讯连接中的一个端点,一个程序将一段信息写入Socket中,该Socket将这段信息发送给另外一个Socket中,使这段信息能传送到其他程序中。你可以这么理解:socket是进程之间用来对话的中间层工具。

二、 socket的作用

 应用层通过传输层进行数据通信时,TCP和UDP会遇到同时为多个应用程序进程提供并发服务的问题。为了区别不同的应用程序进程和连接,许多计算机操作系统为应用程序与TCP/IP协议交互提供了称为套接字(Socket)的接口,区分不同应用程序进程间的网络通信和连接。socket(套接字)是对 TCP/IP 或者UDP/IP协议的封装,Socket本身并不是协议,而是一个调用接口(API),通过Socket,我们才能使用TCP/IP协议。通过这个API程序员在开发网络应用程序的时候,就可以不用关心底层是怎么实现的,减轻开发的难度。

三、  socket的实现方式

1 、  socket的实现方式
生成套接字,socket是一个中间层工具,它存在于操作系统的内核。电脑上的进程为了真正通过socket来发送/接受数据,socket必须和一个能够进行数据传送的接口连接起来,再通过那个接口送出数据。这个接口就是端口,而这个连接的过程就叫做绑定。应用层就可以和传输层通过套接字接口(API),区分来自不同应用程序进程或网络连接的通信,实现数据传输的并发服务。

假设有两个主机要进行通信 Host A和Host B
 Host A上的程序A将一段信息写入Socket中,Socket的内容被Host A的网络管理软件访问,并将这段信息通过Host A的网络接口卡发送到Host B,Host B的网络接口卡接收到这段信息后,传送给Host B的网络管理软件,网络管理软件将这段信息保存在Host B的Socket中,然后程序B才能在Socket中阅读这段信息。

2、  Socket连接的实现方式

要通过互联网进行通信,至少需要一对套接字,一个运行于客户机端,称之为ClientSocket,另一个运行于服务器端,称之为serverSocket。  

基于Tcp协议的Socket通讯类似于B/S架构,面向连接,但不同的是服务器端可以向客户端主动推送消息。

先从服务器端说起。服务器端先初始化Socket,然后与端口绑定(bind),对端口进行监听(listen),调用accept阻塞,等待客户端连接。在这时如果有个客户端初始化一个Socket,要连接的目标是服务器端的套接字,为此,客户端的套接字必须首先描述它要连接的服务器的套接字,指出服务器端套接字的地址和端口号,然后就向服务器端套接字提出连接请求(connect),当服务器端套接字监听到或者说接收到客户端套接字的连接请求,它就响应客户端套接字的请求,建立一个新的线程,把服务器端套接字的描述发给客户端,一旦客户端确认了此描述,连接就建立好了。而服务器端套接字继续处于监听状态,继续接收其他客户端套接字的连接请求。

3.服务器代码:

/**
 * @author: njb
 * @Date: 2020/11/26 18:49
 * @desc: 服务器socket
 */
public class Server {
    public static void main(String[] args) {
        try {
            ServerSocket serverSocket = new ServerSocket(8888);
            System.out.println("----------------服务端执行,開始监听请求----------------");

            Socket socket = serverSocket.accept();//開始监听
            InputStream inputStream = socket.getInputStream();
            //获取请求内容
            String info;
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
            while ((info = bufferedReader.readLine()) != null) {
                System.out.println("我是服务端,客户端请求为:" + info);
            }
            //关闭资源
            socket.shutdownInput();
            bufferedReader.close();
            inputStream.close();
            socket.close();
            serverSocket.close();
        } catch (Exception exception) {
            exception.printStackTrace();
        }
    }
}

4.客户端代码:

/**
 * @author: njb
 * @Date: 2020/11/26 18:49
 * @desc: 客户端socket
 */
public class Client {
    public static void main(String[] args) {
        try {
            //发送到8888端口
            Socket socket = new Socket("127.0.0.1", 8888);
            //输出流
            OutputStream outputStream = socket.getOutputStream();
            PrintWriter printWriter = new PrintWriter(outputStream);
            printWriter.write("服务端你好,我是客户端");
            printWriter.flush();
            //关闭资源
            printWriter.close();
            outputStream.close();
            socket.close();
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

5.启动服务器,运行Server代码:

java socket客户端服务端 FileServer java socket服务端向客户端发消息_客户端

6.启动客户端,发送消息:

java socket客户端服务端 FileServer java socket服务端向客户端发消息_套接字_02

7.socket通信流程为:

java socket客户端服务端 FileServer java socket服务端向客户端发消息_客户端_03