Socket网络编程之基础入门

目录

开头说两句

一、网络编程

二、Socket与TCP、UDP

三、Socket TCP案例简单实现

四、报文、协议、Mac地址

五、IP、端口及远程服务器


开头说两句

国内自年初爆发新冠肺炎疫情到现在,大家应该都是闭门不出吧,各大公司也才开工不久,我本人疫情这段时期也是一直很忙,从年初四到现在都没腾出手来做分享,这篇文章是年前就构思了一直到现在才完成,也是无奈之举,没办法,公司做医疗行业的,所以这段时间业务一直不断,别的不多说了,开始今天的内容——Socket网络编程。

一、网络编程

1、什么是网络?

在计算机领域中,网络是信息传输、接收、共享的虚拟平台,通过它可以把各个点、面、体的信息联系到一起,从而实现这些资源的共享,网络是人类发展史以来最重要的发明,提高了科技和人类社会的发展。

2、局域网

我们的电脑、手机、打印机这些东西都连接到一个路由器上,这就称之为一个局域网,路由器再通过一根网线到达Modem(就是我们平时所说的猫,学名叫作调制解调器),最终通过光纤或者双绞线连接到外面的广域网、因特网,这样就实现了上网的过程。这里说明一点,现在的路由器里面一般都内置了一个Modem的功能,一根网线接到路由器上面,再接到你的电脑,所以上面的图只是一种情况。

3、互联网 

每一个星状的结构可以理解为是一个局域网,无数个局域网组合起来就是互联网,同时还包含了广域网、城域网,这些东西组合之后就是我们的互联网。

4、什么是网络编程

网络编程从大的方面说就是对信息的发送到接收,通过操作相应Api调度计算机硬件资源,并利用传输管道(网线)进行数据交换的过程。举个栗子:比如在我们做手机开发的过程中,我们手机需要调用服务器端的接口,就实现了把我们的json数据传输到后台去,这就涉及到我们调用的api,这个api调用之后在手机的硬件层面所做的操作对上层而言是屏蔽的,这里就利用了管道就是网线,当然手机上没有网线,它是通过无线跟基站进行交互,交换数据之后,基站跟基站之间通过一定的网线来传输数据,最终调度到服务器上,这就是一个传输的过程。这里主要涉及两方,发送方和接收方,发送方可能是json或字符串,想要传输就需要转换成对应的电信号,想要转换成对应的电信号,就需要一定的加工处理,每一次相对完整的独立的加工步骤就是一个处理层,后面会说到七层网络模型。更为具体的涉及:网络模型、套接字、数据包。

5、网络模型

从上面这张图中我们可以看到,这里一共是分为两部分说明:发送方和接收方

发送方:首先是应用层就是你的应用;假如你的app要传输数据,它就需要调用到表示层,表示层其实就是把应用数据表示成对应的数据层面的东西,比如你的字符串要转换成byte类型的数据,就是需要一定的转换;接着进入会话层,会话层就是对不同机器之间进行会话管理;接着进入下一层传输层,传输层就是接收上一层的数据,在必要的时候将数据进行分割,并将这些数据交给网络层,并且要保证这些数据段的有效性;下一层进入网络层,它的主要作用就是控制子网的运行,比如逻辑地址进行分组传输以及路由的选择;再后面是数据链路层,主要作用是进行物理地址的寻找,同时将原始比特流转化为逻辑传输路线;最下面就是物理层,它是机械的接口通信上原始的比特流传输,就是原始电信号的传输,接收方的话就是反过来将原始的电信号或者光信号经过数据链路层的转换依次解析向上传递至应用层,总结一下如下:

基础层:物理层、数据链路层、网络层

传输层:TCP-UDP协议层、Socket

高级层:会话层、表示层、应用层

6、网络模型-对应关系

这张图最左边是我们之前看到的七层的OSI模型,往右是TCP/IP协议层,这里相对于七层网络模型分的更加广阔一些,最右边是细分了每一层都有哪些东西。

二、Socket与TCP、UDP

1、什么是Socket

简单来说是IP地址与端口的结合协议(RFC 793),是一种地址与端口的结合描述协议,是TCP/IP协议的相关API的总称,是网络Api的集合实现,涵盖了Stream Socket/Datagram Socket。

2、Socket的作用与组成

在网络传输中用于唯一标示两个端点之间的链接,端点包括IP+Port,有4个要素:客户端地址、客户端端口、服务器地址、服务器端口。

3、Socket传输原理

这里可以对应着四大要素看一下,客户端和服务器各有一个IP地址,然后端口是25号端口,IP+Port就等于Socket协议了,这里举例是一个邮件服务器,客户端通过25号端口去向服务器取邮件,有的话服务器就给客户端一个返回,这个过程就是socket传输原理的过程。

4、Socket之TCP

TCP是面向连接的通信协议,通过三次握手建立连接,通讯完成时要拆除连接,由于TCP是面向连接的所以只能用于端到端通讯。

5、Socket之UDP

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

三、Socket TCP案例简单实现

单纯的说理论,有点枯燥乏味,这一部分,使用Socket来简单的写个小案例,实现简单的消息收发流程:

客户端代码:

import java.io.*;
import java.net.Inet4Address;
import java.net.InetSocketAddress;
import java.net.Socket;

/**
 * 客户端
 */
public class Client {

    public static void main(String[] args) throws IOException {
        Socket socket = new Socket();
        //设置超时时间
        socket.setSoTimeout(3000);
        //使用ipv4本机地址,端口2000 超时时间3s
        socket.connect(new InetSocketAddress(Inet4Address.getLocalHost(), 2000), 3000);
        System.out.println("连接服务器------");
        System.out.println("客户端信息:地址:" + socket.getLocalAddress() + ",端口:" + socket.getLocalPort());
        System.out.println("服务器信息:地址:" + socket.getInetAddress() + ",端口:" + socket.getPort());

        try {
            sendMessage(socket);
        } catch (Exception e) {
            System.out.println("异常关闭");
        }

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

    //发送数据
    private static void sendMessage(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输入流,并转换为BufferReader
        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 ("exit".equalsIgnoreCase(echo)) {
                flag = false;
            } else {
                System.out.println(echo);
            }
        } while (flag);

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

}

服务端代码:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * 服务器端
 */
public class Server {
    public static void main(String[] args) throws IOException {
        //监听2000端口
        ServerSocket server = new ServerSocket(2000);

        System.out.println("服务器准备就绪------");
        System.out.println("服务器信息:地址" + server.getInetAddress() + ",端口:" + server.getLocalPort());

        //等待客户端连接,构建一个无限循环
        for (;;) {
            //得到客户端
            Socket client = server.accept();
            //客户端构建异步线程
            ClientHandler handler = new ClientHandler(client);
            //启动异步线程
            handler.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() + ",端口:" + socket.getPort());
            try {
                //得到打印流,用于数据输出;服务器回送数据使用
                PrintStream socketOutput = new PrintStream(socket.getOutputStream());
                //得到输入流,用于接收数据
                BufferedReader socketInput = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                do {
                    //客户端拿到一条数据
                    String str = socketInput.readLine();
                    if ("exit".equalsIgnoreCase(str)) {
                        flag = false;
                        //回送
                        socketOutput.println("exit");
                    } else {
                        //打印到屏幕,并回送数据长度
                        System.out.println(str);
                        if (str.equalsIgnoreCase("我是客户端")){
                            socketOutput.println("我是服务端");
                        }else {
                            socketOutput.println("回送客户端消息长度--->"+str.length());
                        }
                    }
                } while (flag);
                socketInput.close();
                socketOutput.close();
            } catch (Exception e) {
                System.out.println("连接异常断开");
            } finally {
                //连接关闭
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("客户端已退出!地址:" + socket.getInetAddress() + ",端口:" + socket.getPort());
        }
    }
}

运行结果如下:这里开了两个窗口,方便操作和查看,左侧是服务端,右侧是客户端,整个流程跟我们代码中设计的是完全一致的,不同的客户端端口是不一致的,单个客户端退出时,服务端仍然保持着连接状态,等待其它客户端连接。

四、报文、协议、Mac地址

1、报文段

报文段是指TCP/IP协议网络传输过程中,起着路由导航作用,用以查询各个网络路由网段、IP地址、交换协议等IP数据包,报文段充当整个TCP/IP协议数据包的导航路由功能,报文在传输过程中会不断地封装成分组、包、帧来传输,封装的方式就是添加一些控制信息组成的首部,即报文头。

2、传输协议

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

3、Mac地址

Media Access Control或者Medium Access Control;意译为媒体访问控制,或称为物理地址、硬件地址,用来定义网络设备的位置,形如:44-45-53-54-00-00,与身份证类似,例如下图中的地址:

五、IP、端口及远程服务器

1、IP地址

互联网协议地址(英文:Internet Protocol Address,又译为网际协议地址),缩写为IP地址(英文:IP Address),是分配给网络上使用网际协议的设备的数字标签,常见的IP地址分为IPV4和IPV6两大类。

IPV4:IP地址由32位二进制数组成,常以xxx.xxx.xxx.xxx形式表现,每组xxx代表小于或等于255的十进制数,比如:208.80.152.2。分为A、B、C、D、E五大类,其中E类属于特殊保留地址,总数量42亿个,在2011/02/03日用尽。如果主机号全部是1,那么这个地址为直接广播地址,如果全部是255,则是受限广播地址。

IPV6:总共有128位长,表现形式一般是采用32个十六进制数表示,由两个逻辑部分组成:一个64位的网络前缀和一个64位的主机地址,主机地址通常根据物理地址自动生成,叫做EUI-64(或者64位扩展唯一标识),例如:2001:0db8:85a3:0000:1319:8a2e:0370:7344,IPV4转换为IPV6一定可以,IPV6转IPV4不一定可以。

2、端口

如果把IP地址比作一间房子,端口就是门或者窗户,0-1023号端口以及1024-49151号端口都是特殊端口

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

3、远程服务器

局域网:一般来说,家里的环境以及公司相互电脑之间环境都属于局域网,我与你的电脑之间属于互联网,而非局域网,默认我的电脑无法直接链接到你的电脑,连接示意图如下:

Web请求流程如下:

写到这里就简单的把Socket的基本概念和使用说完了,这一个系列内容还是很多的,边学边做笔记吧,路漫漫其修远兮,必将上下而求索,加油,各位!

发布了48 篇原创文章 · 获赞 47 · 访问量 9万+

猜你喜欢

转载自blog.csdn.net/JArchie520/article/details/103803084