【网络原理】网络编程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。

如果对您有帮助的话,

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

如果对您有帮助的话,

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

如果对您有帮助的话,

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

相关文章
|
10天前
|
Kubernetes 网络协议 Python
Python网络编程:从Socket到Web应用
在信息时代,网络编程是软件开发的重要组成部分。Python作为多用途编程语言,提供了从Socket编程到Web应用开发的强大支持。本文将从基础的Socket编程入手,逐步深入到复杂的Web应用开发,涵盖Flask、Django等框架的应用,以及异步Web编程和微服务架构。通过本文,读者将全面了解Python在网络编程领域的应用。
13 1
|
13天前
|
Java
[Java]Socket套接字(网络编程入门)
本文介绍了基于Java Socket实现的一对一和多对多聊天模式。一对一模式通过Server和Client类实现简单的消息收发;多对多模式则通过Server类维护客户端集合,并使用多线程实现实时消息广播。文章旨在帮助读者理解Socket的基本原理和应用。
14 1
|
19天前
|
消息中间件 监控 网络协议
Python中的Socket魔法:如何利用socket模块构建强大的网络通信
本文介绍了Python的`socket`模块,讲解了其基本概念、语法和使用方法。通过简单的TCP服务器和客户端示例,展示了如何创建、绑定、监听、接受连接及发送/接收数据。进一步探讨了多用户聊天室的实现,并介绍了非阻塞IO和多路复用技术以提高并发处理能力。最后,讨论了`socket`模块在现代网络编程中的应用及其与其他通信方式的关系。
|
22天前
|
网络协议 Linux 应用服务中间件
Socket通信之网络协议基本原理
【10月更文挑战第10天】网络协议定义了机器间通信的标准格式,确保信息准确无损地传输。主要分为两种模型:OSI七层模型与TCP/IP模型。
|
1月前
|
网络协议 安全 Java
Java Socket原理
Java Socket原理是指在Java中通过Socket实现的网络通信的基础理论与机制。Socket是网络中不同设备间通信的一种标准方式,它允许应用程序之间通过TCP/IP等协议进行数据交换。在Java中,利用Socket编程可以方便地创建客户端与服务器端应用,实现跨网络的数据传输功能,是互联网软件开发中的重要技术之一。它支持多种通信模式,如可靠的流式套接字(TCP)和数据报式套接字(UDP)。
|
1月前
|
网络协议 测试技术 网络安全
Python编程-Socket网络编程
Python编程-Socket网络编程
|
2月前
|
网络协议
关于套接字socket的网络通信。&聊天系统 聊天软件
关于套接字socket的网络通信。&聊天系统 聊天软件
|
4月前
|
网络协议 开发者 Python
深度探索Python Socket编程:从理论到实践,进阶篇带你领略网络编程的魅力!
【7月更文挑战第25天】在网络编程中, Python Socket编程因灵活性强而广受青睐。本文采用问答形式深入探讨其进阶技巧。**问题一**: Socket编程基于TCP/IP,通过创建Socket对象实现通信,支持客户端和服务器间的数据交换。**问题二**: 提升并发处理能力的方法包括多线程(适用于I/O密集型任务)、多进程(绕过GIL限制)和异步IO(asyncio)。**问题三**: 提供了一个使用asyncio库实现的异步Socket服务器示例,展示如何接收及响应客户端消息。通过这些内容,希望能激发读者对网络编程的兴趣并引导进一步探索。
50 4
|
4月前
|
网络协议 Python
网络世界的建筑师:Python Socket编程基础与进阶,构建你的网络帝国!
【7月更文挑战第26天】在网络的数字宇宙中,Python Socket编程是开启网络世界大门的钥匙。本指南将引领你从基础到实战,成为网络世界的建筑师。
63 2
|
4月前
|
网络协议 程序员 视频直播

热门文章

最新文章