Socket网络编程入门

MysteryJack

什么是网络编程

什么是网络?

在计算机领域中,网络是信息传输、接受、共享的虚拟平台。

通过它把各个点、面、体的信息联系到一起,从而实现这些资源的共享。

什么是网络编程?

网络编程从大的方面就是说对信息的发送接收。

通过操作相应API调度计算机资源硬件,并且利用管道(网线)进行数据交互的过程。

更为具体的涉及:网络模型、套接字、数据包。

7层网络模型-OSI

互联网的本质就是一系列的网络协议,这个协议就叫OSI协议(一系列协议),按照功能不同,分工不同,人为的分层七层。实际上这个七层是不存在的。没有这七层的概念,只是人为的划分而已。区分出来的目的只是让我们明白哪一层是干什么用的。

每一层都运行不同的协议。

实际上也可以把它划成五层、四层。

七层划分为:应用层、表示层、会话层、传输层、网络层、数据链路层、物理层

五层划分为:应用层、传输层、网络层、数据链路层、物理层

四层划分为:应用层、传输层、网络层、网络接口层

网络模型

应用层

用户使用的都是应用程序,均工作于应用层,大家都可以开发自己的应用程序,数据多种多样,必须规定好数据的组织形式 。

应用层功能:规定应用程序的数据格式。

比如TCP协议可以为各种各样的程序传递数据,比如Email、WWW、FTP等。那么,必须有不同协议规定电子邮件、网页、FTP数据的格式,这些应用程序协议就构成了”应用层”。

应用层

表示层

表示层的用途是提供一个可供应用层选择的服务的集合,使得应用层可以根据这些服务功能解释数据的含义。表示层以下各层只关心如何可靠地传输数据,而表示层关心的是所传输数据的表现方式、它的语法和语义。表示服务的例子有统一的数据编码、数据压缩格式和加密技术等。

表示层

会话层

会话层任务是:向两个实体的表示层提供建立和使用连接的方法。将不同实体之间的表示层的连接称为会话。因此会话层的任务就是组织和协调两个会话进程之间的通信,并对数据交换进行管理。

会话层

传输层

传输层是通信子网和资源子网的接口和桥梁,起到承上启下的作用。

该层的主要任务是:向用户提供可靠的端到端的差错和流量控制,保证报文的正确传输。传输层的作用是向高层屏蔽下层数据通信的细节,即向用户透明地传送报文。

该层常见的协议:TCP/IP中的TCP协议、Novell网络中的SPX协议和微软的NetBIOS/NetBEUI协议。

传输层提供会话层和网络层之间的传输服务,这种服务从会话层获得数据,并在必要时,对数据进行分割。然后,传输层将数据传递到网络层,并确保数据能正确无误地传送到网络层。因此,传输层负责提供两节点之间数据的可靠传送,当两节点的联系确定之后,传输层则负责监督工作。综上,传输层的主要功能如下:
传输连接管理:提供建立、维护和拆除传输连接的功能。传输层在网络层的基础上为高层提供面向连接面向无连接的两种服务。

传输层

网络层

网络层的作用是在网络与网络相互连接的环境中,将数据从发送端主机发送到接受端主机。

举例:

我在学校教室中,我想找隔壁班的妹子,我通知小弟去告诉她,说有个帅哥找你。而小弟就是网关IP地址就是我所处的教室,MAC地址就是我在教室的某个位置。

网络层

数据链路层、物理层

早期的时候,数据链路层就是来对电信号来做分组的。以前每个公司都有自己的分组方式,非常的乱,后来形成了统一的标准,即以太网协议Ethernet。

通信传输实际上是通过物理的传输介质实现的。数据链路层的作用就是在这些同构传输介质互连的设备之间进行数据处理。

物理层中,将数据的 0 、1转换为电压和脉冲光传输给物理的传输介质,而相互直连的设备之间使用地址实现传输。这种地址被称为 MAC 地址,也可称为物理地址或硬件地址。采用 MAC 地址信息的首部附加到从网络层转发过来的数据上,将其发送到网络。

网络层与数据链路层都是基于目标地址将数据发送给接收端的,但是网络层负责将整个数据发送给最终目标地址。而数据链路层则只负责发送一个分段内的数据。

OSI七层网络模型TCP/IP四层概念模型对应网络协议
应用层(Application)应用层HTTP、TFTP, FTP, NFS, WAIS、SMTP
表示层(Presentation)应用层Telnet, Rlogin, SNMP, Gopher
会话层(Session)应用层SMTP, DNS
传输层(Transport)传输层TCP, UDP
网络层(Network)网络层IP, ICMP, ARP, RARP, AKP, UUCP
数据链路层(Data Link)数据链路层FDDI, Ethernet, Arpanet, PDN, SLIP, PPP
物理层(Physical)数据链路层IEEE 802.1A, IEEE 802.2到IEEE 802.11

OSI的封包与解包过程

OSI七层数据协议数据传输时的封包与解包过程

Socket与TCP、UDP

什么是Socket

  • 简单来说是IP地址与端口的结合协议(RFC 793)
  • 一种地址与端口的结合描述协议。
  • TCP/IP 协议的相关API的总称;是网络API的集合实现。
  • 在计算机通信领域,Socket 被翻译为“套接字”,它是计算机之间进行通信的一种约定或一种方式。通过 Socket 这种约定,一台计算机可以接收其他计算机的数据,也可以向其他计算机发送数据。

Socket的作用与组成

  • 在网络传输中用于唯一标识两个端点之间的连接。
  • 端点:包括(IP + Port)
  • 四个要素:客户端地址、客户端端口、服务器地址、服务器端口。

Socket流程

Socket流程

服务器端先初始化Socket,然后与端口绑定(bind),对端口进行监听(listen),调用accept开始阻塞,等待客户端连接。在这时如果有个客户端初始化一个Socket,然后连接服务器(connect),如果连接成功,这时客户端与服务器端的连接就建立了。客户端发送数据请求,服务器端接收请求并处理请求,然后把回应数据发送给客户端,客户端读取数据,最后关闭连接,一次交互结束。

Socket 之 TCP

  • TCP是面向连接的通信协议
  • 通过三次握手建立连接,通讯完成时要拆除连接

    • 第一次握手:客户端发送带有 SYN 标志的连接请求报文段,然后进入 SYN_SEND 状态,等待服务端确认。
    • 第二次握手:服务端接受到客户端的 SYN 报文段后,需要发送 ACK 信息对这个 SYN 报文段进行确认。同时,还要发送自己的 SYN 请求信息。服务端会将上述信息放到一个报文段(SYN+ACK 报文段)中,一并发送给客户端,此时服务端进入 SYN_RECV 状态。
    • 第三次握手:客户端接收到服务端的 SYN+ACK 报文段后,会向服务端发送 ACK 确认报文段,这个报文段发送完毕后,客户端和服务端都进入 ESTABLEISHED 状态,完成 TCP 三次握手。

      TCP 三次握手

  • 由于TCP是面向连接的所以只能用于端到端的通讯。

Socket 之 UDP

  • UDP是面向无连接的通讯协议。
  • UDP数据包括目标端口号和源端口号信息。
  • 由于通讯不需要连接,所以可以实现广播发送,并不局限于端到端。

UDP传输

Client-Server Application

  • TCP/IP 协议中,两个进程间通信的主要模式为:CS模型。
  • 主要目的:协同网络中的计算机资源、服务模式、进程间数据共享。
  • 常见的:HTTPFTPSMTP

Socket TCP 基础代码实战

客户端代码:

/**
 * @author Jack
 */
public class Client {
    public static void main(String[] args) throws IOException {
        Socket socket = new Socket();
        // 超时时间
        socket.setSoTimeout(3000);

        // 连接本地,端口2000;超时时间3000ms
        socket.connect(new InetSocketAddress(Inet4Address.getLocalHost(), 2000), 3000);

        System.out.println("已发起服务器连接...");
        System.out.println("客户端信息:" + socket.getLocalAddress() + " P:" + socket.getLocalPort());
        System.out.println("服务器信息:" + socket.getInetAddress() + " P:" + socket.getPort());

        try {
            // 发送接收数据
            todo(socket);
        } catch (Exception e) {
            System.out.println("异常关闭");
        }

        // 释放资源
        socket.close();
        System.out.println("客户端已退出~");

    }

    private static void todo(Socket client) throws IOException {
        // 构建键盘输入流
        InputStream in = System.in;
        BufferedReader input = new BufferedReader(new InputStreamReader(in));

        // 得到Socket输出流,并转换为打印流
        OutputStream outputStream = client.getOutputStream();
        PrintStream socketPrintStream = new PrintStream(outputStream);

        // 得到Socket输入流,并转换为BufferedReader
        InputStream inputStream = client.getInputStream();
        BufferedReader socketBufferedReader = new BufferedReader(new InputStreamReader(inputStream));

        boolean flag = true;
        do {
            // 键盘读取一行
            String str = input.readLine();
            // 发送到服务器
            socketPrintStream.println(str);
            // 从服务器读取一行
            String echo = socketBufferedReader.readLine();
            if ("bye".equalsIgnoreCase(echo)) {
                flag = false;
            } else {
                System.out.println(echo);
            }
        } while (flag);

        // 资源释放
        socketPrintStream.close();
        socketBufferedReader.close();

    }

}

服务端代码:

/**
 * @author jack
 */
public class Server {

    public static void main(String[] args) throws IOException {
        ServerSocket server = new ServerSocket(2000);

        System.out.println("服务器准备就绪...");
        System.out.println("服务器信息:" + server.getInetAddress() + " P:" + server.getLocalPort());

        // 等待客户端连接
        for (; ; ) {
            // 得到客户端
            Socket client = server.accept();
            // 客户端构建异步线程
            ClientHandler clientHandler = new ClientHandler(client);
            // 启动线程
            clientHandler.start();
        }

    }

    /**
     * 客户端消息处理
     */
    private static class ClientHandler extends Thread {
        private Socket socket;
        private boolean flag = true;

        ClientHandler(Socket socket) {
            this.socket = socket;
        }

        @Override
        public void run() {
            super.run();
            System.out.println("新客户端连接:" + socket.getInetAddress() + " P:" + socket.getPort());
            try (// 得到打印流,用于数据输出;服务器回送数据使用
                 PrintStream socketOutput = new PrintStream(socket.getOutputStream());
                 // 得到输入流,用于接收数据
                 BufferedReader socketInput = new BufferedReader(new InputStreamReader(
                         socket.getInputStream()))) {
                do {
                    // 服务器拿到拿到一条数据
                    String str = socketInput.readLine();
                    if ("bye".equalsIgnoreCase(str)) {
                        flag = false;
                        // 回送
                        socketOutput.println("bye");
                    } else {
                        // 打印到屏幕。并回送数据长度
                        System.out.println(str);
                        socketOutput.println("服务器收到了,你发送的长度为 :" + str.length());
                    }
                } while (flag);
            } catch (Exception e) {
                System.out.println("连接异常断开");
            } finally {
                // 连接关闭
                if (socket != null) {
                    try {
                        socket.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
            System.out.println("客户端已退出:" + socket.getInetAddress() + " P:" + socket.getPort());
        }
    }

}

运行结果:

服务端

客户端

报文、协议、Mac地址、IP、端口

报文段

  • 报文段是指TCP/IP协议网络传输过程中,起着路由导航作用。
  • 用于查询各个网络路由网段、IP地址、交换协议等IP数据包。
  • 报文在传输过程中会不断地封装成分组、包、帧来传输。

传输协议

  • 协议顾名思义,一种规定,约束。
  • 约定大于配置,在网络传输中依然适用;网络的传输流程是很健壮的稳定的,得益于基础的协议构成。
  • 简单来说: A -> B 的传输数据,B能识别,反之 B -> A 的传输数据 A也能识别,这就是协议。

Mac地址

  • Media Access Control 或者 Medium Access Control。
  • 意译为媒体访问控制,或称为物理地址、硬件地址。
  • 用来定义网络设备位置。
  • 通常被固化在每个以太网网卡(NIC,Network Interface Card)。MAC(硬件)地址长48位(6字节),采用十六进制格式。
  • 比如:44-45-53-54-00-00 。

    MAC地址及其组成部分

IP地址

  • 互联网协议地址(Internet Protocol Address)。
  • 是分配给网络上使用网际协议的设备的数字标签。
  • 常见的IP地址分为IPv4,IPv6
  • IP地址由32位二进制数组成,常以XXX.XXX.XXX.XXX形式出现,每组XXX代表小于或等于255的10进制数。
  • IP地址分为A、B、C、D、E五大类,其中E类属于特殊保留地址。

IP地址 - IPv4

  • 总数量:4,294,967,296个(即232):42亿个;最终于2011年2月3日用尽。
  • 如果主机号都是1,那么这个地址为直接广播地址。
  • IP地址 "255.255.255.255" 为受限广播地址。

IP地址 - IPv6

  • 总共有128位长,IPv6地址的表达形式,一般采用32个十六进制。
  • 由两个逻辑部分组成:一个64位的网络前缀和一个64位的主机地址,主机地址通常根据物理地址自动生成,叫做EUI-64。
  • 2001:0db8:85a3:0000:1319:8a2e:0370:7344
  • IPv4可以转换为IPv6,但IPv6不一定能转换为IPv4。

端口

  • 如果把IP地址比做一间房子,端口就是出入这间房子的门或者窗户。
  • 外界的信息飞到不同窗户也就是给不同的人传递信息。
  • 0-49151号端口都是特殊端口。

常见的特殊端口

  • 计算机之间依照互联网传输层 TCP/IP 协议的协议通信,不同协议都对应不同的端口。
  • 49152到65535号端口属于“动态端口”范围,没有端口可以被正式占用。
阅读 421

Java菜鸟程序员
Be a good developer .微信公众号:Java菜鸟程序员
575 声望
313 粉丝
0 条评论
你知道吗?

575 声望
313 粉丝
宣传栏