【网络原理】网络编程Socket套接字基础知识汇总

简介: 【网络原理】网络编程Socket套接字基础知识汇总

1.网络初始:

  1. 局域网(LAN)广域网(WAN)
  2. IP地址用于定位主机的网络地址。端口号可以标识主机中发送数据接收数据的进程(用于定位主机中的进程)。一个端口只能被一个进程绑定(通常情况),但是一个进程可以绑定多个端口号。
  3. 协议是俩个人的事情,只有双方都了解并且遵守才有意义!
  4. 协议分层,上层协议调用下层协议,下层协议给上层协议提供服务,相邻的层是可以相互交互的,但是不能跨层级。
  5. TCP/IP五层网络模型和封装,假设主机A给主机B发了个helloworld 主机A发送的过程 一.应用层   应用程序会把输入的helloworld构造成约定好的应用层协议的报文    应用程序就会把这个应用数据报文,交给传输层协议    传输层是操作系统内核实现的,操作系统提供了一些API给应用程序,    这些API叫做socket api,代码调用这些api就可以把应用层的数据交给传输层(交给了操作系统内核)二.传输层   传输层这里有很多协议,最典型的就是TCP协议,此处以TCP为例    TCP协议要在之前的基础上,加上个TCP的协议报头    这个TCP报头里面最重要的就是源端口和目的端口!    传输层继续将这个数据交给网络层进行处理         三.网络层   网络层中最典型的就是IP协议   IP协议把整个TCP数据看成整体,作为载荷部分,在前头加上IP协议报头    IP协议报头里面有很多信息,最关键的就是源IP和目的IP   构造好IP数据报之后,IP协议继续把整个数据交给数据链路层         四.数据链路层   数据链路层的协议有很多,最典型的就是以太网    以太网这个歌协议既管数据链路层,又管物理层    以太网数据帧将IP数据报的前头加上帧头(源mac地址和目的mac地址),后头加上帧尾(校验和) 五.物理层   到达物理层的数据已经组织好了    就可以通过物理层设备(网卡)把上述数据的二进制bit流转换成光信号或电信号来传输
  6. 分用就是封装的逆过程,封装是打包快递,而分用就是拆开快递。
  7. 网络中的细节太多了,如果一个协议搞定,那这个协议就会非常的复杂。因此就需要拆分,拆分的多了,又要分层。拆分之后,一个协议负责一件事情,这样才把这些关键信息放到了不同的协议报头中。

2.网络编程

  1. 网络编程指的是网络上的主机,通过不同的进程,以编程的方式实现网络通信网络编程主要是针对应用层。
  2. 网络编程套接字,就是研究如何写代码完成网络编程。socket api是一切网络编程的基础。
  3. socket套接字是操作系统给应用程序提供的API,描述的是应用层和传输层的交互其实socket api就是传输层给应用层提供的
  4. API就是一组类和方法。应用程序就可以通过socket api来进行网络编程(操作网卡)。
  5. 网络传输层中又很多种协议,最主要的就是TCP和UDP。因此操作系统就提供了俩个不同的版本的API。
  6. 传输层中TCP和UDP的区别
TCP UDP
有连接 无连接
可靠传输 不可靠传输
面向字节流 面向数据报
全双工 全双工

  1. TCP和文件操作一样是基于“流”的,而UDP则是以“数据报”为基本单位。全双工是一个通道,双向通信;半双工是一个通道,单向通信。网络通信一般都是全双工的。有连接就相当于打电话,必须通信的双方建立好了连接才可以正常打电话;而无连接相当于发短信,直接就可以发送过去。

3.UDP数据报套接字

  1. DatagramSocketDatagramPacket是UDP socket需要掌握的类。
  2. DatagramSocket,是网卡的代言人,借助这个类来读写网卡。通过网卡发送数据就是写文件,接收数据就是读文件。
方法签名 说明
DatagramSocket() 一般用于客户端,创建一个UDP数据报套接字的socket,绑定到随机一个端口
DatagramSocket(int port) 一般用于服务器,创建一个UDP数据报套接字的socket,绑定到指定端口
void receive(DatagramPacket p ) 接收数据报,没有收到会阻塞等待
void send(DatagramPacket p ) 发送数据报,不会阻塞等待
void close() 关闭数据报套接字

  1. socket本质上是一个文件。socket对应到网卡这个硬件设备,操作系统也是把网卡当作文件来管理。通过网卡发送数据,就是写文件;通过网卡接收数据,就是读文件。
  2. DatagramPacket,代表一个UDP数据包,是一次发送/接受的基本单位;发送和接收的是DatagramPacket。
方法签名 说明
DatagramPacket(byte[ ] b,int length) 构造一个DatagramPacket用来接收数据报,接收的数据保存在字节数组里
DatagramPacket(byte[ ] b,int offset,int length,address) 构造一个DatagramPacket用来发送数据报,发送的数据为字节数组的指定长度。address为指定目的主机的IP和端口号
getAddress() 从接收的数据报中获取发送端主机IP地址;或从发送的数据报中获取接收端主机IP地址
int getPort() 从接收的数据报中获取发送端主机端口号;或从发送的数据报中获取接收端主机端口号
byte[ ] getData() 获取数据报中的数据

  1. UDP实现回显服务器(服务器部分)
//UDP版本:回显服务器的服务器部分
public class UdpEchoServer {
    private DatagramSocket socket = null;
    //参数的端口表示服务器要绑定的端口
    //不需要指定IP,就是本机的IP
    public UdpEchoServer(int port) throws SocketException {
        socket = new DatagramSocket(port);
    }
    //启动服务器
    public void start() throws IOException {
        System.out.println("服务器启动了!!!");
        while(true){
            //1.读取请求并且解析
            //socket的receive操作需要一个空的requestPacket,receive方法的参数是一个输出型参数
            //将空的DatagramPacket对象交给receive,在receive里面负责把从网卡读到的数据填充到这个对象中
            DatagramPacket requestPacket = new DatagramPacket(new byte[1024],1024);//要给DatagramPacket申请内存空间
            socket.receive(requestPacket);
            //将DatagramPacket转换成字符串    getData()是获取数据报中的数据,返回一个byte[]
            String request = new String(requestPacket.getData(),0, requestPacket.getLength());
            //2.根据请求计算响应
            String response = process(request);
            //3.把响应返回给客户端
            //发送DatagramPacket对象需要指定IP地址和端口号
            DatagramPacket responsePacket = new DatagramPacket(    //getSocketAddress就是得到客户端的IP和端口号
                    response.getBytes(),response.getBytes().length, requestPacket.getSocketAddress());
            socket.send(responsePacket);
            //4.打印一个日志
            System.out.printf("[%s %d]: req: %s ; resp: %s\n",
                    requestPacket.getAddress().toString(),requestPacket.getPort(),request,response);
        }
    }
    public String process(String request) {
        return request;
    }
    public static void main(String[] args) throws IOException {
        UdpEchoServer server = new UdpEchoServer(1025);
        server.start();
    }
}
  1. UDP实现回显服务器(客户端部分)
//UDP版本:回显服务器的客户端部分
public class UdpEchoClient {
    private DatagramSocket socket = null;
    private String serverIP;
    private int serverPort;
    //服务器的IP一般不用写,就是本机的IP
    //需要传服务器的IP和服务器的端口
    public UdpEchoClient(String serverIp,int serverPort) throws SocketException {
        socket = new DatagramSocket();//不用指定参数
        this.serverIP = serverIp;
        this.serverPort = serverPort;
    }
    public void start() throws IOException {
        Scanner scanner = new Scanner(System.in);
        while(true){
            //1.从控制台上读取用户输入的内容
            System.out.print("-> ");
            String request = scanner.nextLine();
            //2.构造一个UDP请求,发送给服务器
            DatagramPacket requestPacket = new DatagramPacket(
                    //request.getBytes().length这里的length单位是字节
                    //request.length()这里的length()单位是字符,不可以改成这样
                    request.getBytes(),request.getBytes().length, InetAddress.getByName(this.serverIP),this.serverPort);
            socket.send(requestPacket);
            //3.从服务器接收响应,并且转成字符串
            DatagramPacket responsePacket = new DatagramPacket(new byte[1024],1024);
            socket.receive(responsePacket);
            String response = new String(responsePacket.getData(),0, responsePacket.getLength());
            //4.把响应显示到控制台上
            System.out.println(response);
        }
    }
    public static void main(String[] args) throws IOException {
        //IP是某某食堂,端口号是某某窗口
        UdpEchoClient client = new UdpEchoClient("127.0.0.1",1025);
        client.start();
    }
}
  1. DatagramPacket的三种构造方法
  2. 为什么服务器需要指定端口,而客户端不用指定端口???答:服务器指定端口目的就是方便客户端找到服务器在哪而客户端不指定端口因为操作系统会分配一个空闲的端口,如果手动指定了万一用户电脑上的其他程序占用了这个端口,就会导致程序无法正确运行了。
  3. 对于服务器来说,读取请求并且解析根据请求计算响应把响应写回到客户端执行的速度是极快的。如果有多个客户端同时发来请求,服务器也是可以响应的,但是本质上这三个请求的串行处理的!
  4. 当前俩个程序放在同一个主机上是通过127.0.0.1这个IP来通信的;也可以把俩个程序放在不同的主机上也是可以通信的,但是如果放在不同的主机上,要确保服务器的地址是可以访问到的!

4.TCP流套接字:

  1. ServerSocketSocket是TCP流套接字需要掌握的俩个类。
  2. ServerSocket是创建TCP服务器的api,给服务器使用的类,用来监听端口
方法签名 说明
ServerSocket(int port) 创建一个服务端流套接字Socket,并且绑定指定端口
Socket accept() 有客户端连接后,返回一个服务端Socket对象,并基于该Socket建立与客户端的连接否则阻塞等待
void close() 关闭此套接字

  1. Socket既会给服务器使用也会给客户端使用,用来传输数据。
方法签名 说明
Socket(String host,int port) 创建一个客户端流套接字Socket,并且尝试和对应IP的主机上对应端口的进程建立连接
InetAddress getInetAddress() 返回套接字所连接的地址,获取IP和端口
int getPort() 返回套接字所连接的端口
InputStream  getInputStream() 返回此套接字的输入流
OutputStream getOutputStream() 返回此套接字的输出流

  1. TCP实现回显服务器(服务器部分)
//TCP版本:回显服务器服务器部分
public class TcpEchoServer {
    private ServerSocket listenSocket = null;
    public TcpEchoServer(int port) throws IOException {
        listenSocket = new ServerSocket(port);
    }
    public void start() throws IOException {
        System.out.println("服务器启动!!");
        //使用线程池
        ExecutorService service = Executors.newCachedThreadPool();
        while(true) {
            //1.先调用accept
            Socket clientSocket = listenSocket.accept();
            //2.再来处理这个连接,这里应该使用多线程,每个客户端连上来都分配一个新的线程负责处理
            //使用多线程确实可以解决问题,但是会频繁的创建和销毁线程!
//            Thread t = new Thread(()->{
//                try {
//                    processConnection(clientSocket);
//                } catch (IOException e) {
//                    throw new RuntimeException(e);
//                }
//            });
//            t.start();
            service.submit(new Runnable() {
                @Override
                public void run() {
                    try {
                        processConnection(clientSocket);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            });
        }
    }
    private void processConnection(Socket clientSocket) throws IOException {
        System.out.printf("[%s:%d] 客户端上线!\n",
                clientSocket.getInetAddress().toString(),clientSocket.getPort());
        //处理客户端的请求
        //clientSocket代表的是服务器的网卡,inputStream代表从网卡读数据也就相当于从客户端读取数据
        try(InputStream inputStream = clientSocket.getInputStream();
            OutputStream outputStream = clientSocket.getOutputStream()){
            while(true){
                //1.读取请求并且解析
                Scanner scanner = new Scanner(inputStream);
                if(!scanner.hasNext()){
                    System.out.printf("[%s:%d] 客户端下线!\n",
                            clientSocket.getInetAddress().toString(),clientSocket.getPort());
                    break;
                }
                String request = scanner.next();
                //2.根据请求计算响应
                String response = process(request);
                //3.把响应写回到客户端
                PrintWriter printWriter = new PrintWriter(outputStream);
                printWriter.println(response);
                //刷新缓冲区确保数据确实是通过网卡发送出去了
                printWriter.flush();
                System.out.printf("[%s:%d] req: %s; resp: %s\n",
                        clientSocket.getInetAddress().toString(),clientSocket.getPort(),request,response);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            //为什么这个clientSocket要关闭文件,前面的listenSocket和UDP程序中的socket都不需要关闭文件呢?
            clientSocket.close();
        }
    }
    public String process(String request) {
        return request;
    }
    public static void main(String[] args) throws IOException {
        TcpEchoServer server = new TcpEchoServer(9090);
        server.start();
    }
}
  1. TCP实现回显服务器(客户端部分)
//TCP版本:回显服务器客户端部分
public class TcpEchoClient {
    private Socket socket = null;
    public TcpEchoClient(String serverIp, int serverPort) throws IOException {
        socket = new Socket(serverIp, serverPort);
    }
    public void start() {
        Scanner scanner = new Scanner(System.in);
        try (InputStream inputStream = socket.getInputStream();
             OutputStream outputStream = socket.getOutputStream()) {
            while (true) {
                //1.从控制台读取数据
                System.out.print("-> ");
                String request = scanner.next();
                //2.发送请求给服务器
                PrintWriter printWriter = new PrintWriter(outputStream);
                printWriter.println(request);
                printWriter.flush();
                //3.从服务器上接收响应
                Scanner respScanner = new Scanner(inputStream);
                String response = respScanner.next();
                //4.把响应显示到界面上
                System.out.println(response);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    public static void main(String[] args) throws IOException {
        TcpEchoClient server = new TcpEchoClient("127.0.0.1",9090);
        server.start();
    }
}
  1. TCP实现回显服务器的服务器代码部分,如果使用1的话,就不能让多个客户端同时使用服务器;如果使用2,频繁的创建和销毁代价较大,所以推荐使用线程池!
  2. TCP实现回显服务器的服务器代码中需要close文件!
  3. 启动服务器,如果没有客户端建立连接,服务器就会阻塞等待。如果有一个客户端过来了,此时就会显示客户端已上线并且向下执行代码。如果再有一个客户端也过来了,使用上述的方案1那么不会显示这个客户端已上线
  4. TCP中的长短连接。TCP发送数据时需要先建立连接,什么时候关闭连接就决定是短连接还是长连接。短连接:每次收到数据并返回响应后,都关闭连接,也就是短连接只能一次收发数据,TCP每个连接只处理一个客户端请求能够保证快速调用到accept。长连接:不关闭连接,一直保持连接状态,双方不停的收发数据,也就是长连接可以多次收发数据,TCP建立连接之后,要处理客户端的多次请求才导致无法快速调用accept。

如果对您有帮助的话,

不要忘记点赞+关注哦,蟹蟹

如果对您有帮助的话,

不要忘记点赞+关注哦,蟹蟹

如果对您有帮助的话,

不要忘记点赞+关注哦,蟹蟹

相关文章
|
2月前
|
网络协议 安全 5G
网络与通信原理
【10月更文挑战第14天】网络与通信原理涉及众多方面的知识,从信号处理到网络协议,从有线通信到无线通信,从差错控制到通信安全等。深入理解这些原理对于设计、构建和维护各种通信系统至关重要。随着技术的不断发展,网络与通信原理也在不断演进和完善,为我们的生活和工作带来了更多的便利和创新。
76 3
|
1天前
|
域名解析 网络协议 关系型数据库
【网络原理】——带你认识IP~(长文~实在不知道取啥标题了)
IP协议详解,IP协议管理地址(NAT机制),IP地址分类、组成、特殊IP地址,MAC地址,数据帧格式,DNS域名解析系统
|
3天前
|
网络协议 安全 网络安全
探索网络模型与协议:从OSI到HTTPs的原理解析
OSI七层网络模型和TCP/IP四层模型是理解和设计计算机网络的框架。OSI模型包括物理层、数据链路层、网络层、传输层、会话层、表示层和应用层,而TCP/IP模型则简化为链路层、网络层、传输层和 HTTPS协议基于HTTP并通过TLS/SSL加密数据,确保安全传输。其连接过程涉及TCP三次握手、SSL证书验证、对称密钥交换等步骤,以保障通信的安全性和完整性。数字信封技术使用非对称加密和数字证书确保数据的机密性和身份认证。 浏览器通过Https访问网站的过程包括输入网址、DNS解析、建立TCP连接、发送HTTPS请求、接收响应、验证证书和解析网页内容等步骤,确保用户与服务器之间的安全通信。
26 1
|
1天前
|
安全 算法 网络协议
【网络原理】——图解HTTPS如何加密(通俗简单易懂)
HTTPS加密过程,明文,密文,密钥,对称加密,非对称加密,公钥和私钥,证书加密
|
1天前
|
存储 JSON 缓存
【网络原理】——HTTP请求头中的属性
HTTP请求头,HOST、Content-Agent、Content-Type、User-Agent、Referer、Cookie。
|
1天前
|
前端开发 网络协议 安全
【网络原理】——HTTP协议、fiddler抓包
HTTP超文本传输,HTML,fiddler抓包,URL,urlencode,HTTP首行方法,GET方法,POST方法
|
1天前
|
XML JSON 网络协议
【网络原理】——拥塞控制,延时/捎带应答,面向字节流,异常情况
拥塞控制,延时应答,捎带应答,面向字节流(粘包问题),异常情况(心跳包)
|
1天前
|
网络协议 算法 Java
【JavaEE】——初始网络原理
局域网,广域网,局域网连接方式,交换机,集线器,路由器,网络通信,五元组(源IP,源端口,目的IP,目的端口,协议),协议分层,TCP/IP五层网络协议,封装和分用,交换机和路由器的封装和分用
|
1月前
|
运维 物联网 网络虚拟化
网络功能虚拟化(NFV):定义、原理及应用前景
网络功能虚拟化(NFV):定义、原理及应用前景
85 3
|
1月前
|
网络协议 安全 算法
网络空间安全之一个WH的超前沿全栈技术深入学习之路(9):WireShark 简介和抓包原理及实战过程一条龙全线分析——就怕你学成黑客啦!
实战:WireShark 抓包及快速定位数据包技巧、使用 WireShark 对常用协议抓包并分析原理 、WireShark 抓包解决服务器被黑上不了网等具体操作详解步骤;精典图示举例说明、注意点及常见报错问题所对应的解决方法IKUN和I原们你这要是学不会我直接退出江湖;好吧!!!
网络空间安全之一个WH的超前沿全栈技术深入学习之路(9):WireShark 简介和抓包原理及实战过程一条龙全线分析——就怕你学成黑客啦!