网络编程入门

本文介绍了网络编程的基础知识,包括网络设备如路由器和网卡,以及互联网的概念。详细讲解了IP地址(IPv4和IPv6)、端口的作用和TCP/UDP协议的区别。TCP提供可靠的数据传输,而UDP则更快但不保证数据到达。此外,还提到了URL的结构和网络连接的建立(三次握手)与关闭(四次挥手)过程,以及Java中通过套接字实现网络通信的示例。最后讨论了单工、半双工和全双工的数据传输模式。
摘要由CSDN通过智能技术生成

网络编程

网络介绍
	网络设备
	互联网是什么
IP
端口
传输控制协议
	TCP
	UDP
URL
单工
半双工
全双工
综合练习即时聊天系统

网络简介

网络设备

要组成一个局域网,必须要有路由器,每一个连接到路由器上的设备必须有网卡,每一个网卡都会有一个mac地址(物理地址),mac地址是唯一的。

在局域网下,所有的数据传输,都会通过路由器去中转,这样通过路由器组成一个局域网,那么路由器和路由器之间再进行互联,就可以形成一个超大的互联网了。

互联网是什么

互联网就是一个超大的局域网

IP

IP是Internet Protocol(网际互连协议)的缩写,是TCP/IP体系中的网络层协议。设计IP的目的是提高网络的可扩展性:一是解决互联网问题,实现大规模、异构网络的互联互通;二是分割顶层网络应用和底层网络技术之间的耦合关系,以利于两者的独立发展。根据端到端的设计原则,IP只为主机提供一种无连接、不可靠的、尽力而为的数据包传输服务。

IPV4

IPV4的长度是32位,理论上有2^32-1这么多个。格式是有三个点,把ip分成了4个部分,每一个部分的值是0-255;比如:xxx.xxx .xxx.xxx

IP是用来识别网络上的地址使用的,由两部分组成:网络地址和主机地址

ipv4分为了5类

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RcfRZfh0-1681793689891)(网络编程.assets/a.png)]

IPV4因为快要耗尽的原因,开发了IPV6

IPV6

ipv6的长度是128位,可以解决IPV4耗尽的问题

特殊IP

回路IP:127.0.0.1 127开头后面除了全0或者全1都称为回路IP

0.0.0.0 也可以代表本机

255.255.255.0

端口

端口的长度是16位,端口可以理解为进入计算机的门,理论上来说端口有2^16个,取值范围是0-65535,每一个端口只能被一个程序占用,一个程序可以占用多个端口,端口打开的越少越安全。

netstat -ano 可以查看所有的端口监听情况

netstat -ano | findstr 3306 可以查看指定端口的情况

上述的两个命令都可以查看到对应的pid,也就可以结合任务管理器,去关闭对应的程序,释放对应监听的端口

固定端口

80 http协议的缺省端口

443 https协议的缺省端口 相比http加密更安全

21 ftp协议的确认端口

3306 mysql的默认端口

25 smtp 邮件发送服务器占用的端口

110 pop3 邮件接收服务器占用的端口

一般来说,自己的程序需要占用端口的时候,尽可能使用的端口往后一些,避免这个端口被占用

传输控制协议

tcp协议

当使用tcp协议的时候,如果A给B发送消息,B收到消息后会给出反馈,A可以知道对方接收到没有,协议更加可靠

七层理论模型

OSI七层模型

7 应用层  提供应用程序之间的通信
6 表示层  处理数据格式,是应用层和网络层之间的翻译官
5 会话层  建立、维护和管理会话
4 传输层  端到端之间的连接
3 网络层  寻址和路由选择,主要功能就是将网络地址翻译成对应的物理地址,并决定如何将数据从发送方路由到接收方
2 数据链路层  介质访问,链路管理,主要功能就是如何在不可靠的物理线路上进行可靠的数据传递
1 物理层  比特流传输

四层模型

应用层
传输层
网络层
数据链路层

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5tIrw5zv-1681793689892)(网络编程.assets/wps1.png)]

三次握手

建立连接需要三次握手,才可以保证这个连接是可靠的

假设A 给B 发消息

  1. A给B发一个消息 B收到了 B知道A可以发消息,B可以收消息
  2. B 给A 回一个消息 A收到了 A知道B可以发送和接收消息 A知道自己可以发送和接口
  3. A 给B回一个消息 B收到消息 B知道B可以发送消息

这样的连接建立起来才是可靠的

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xpEsJwyo-1681793689892)(网络编程.assets/9d82d158ccbf6c819624f31141341c3332fa40cd.jpeg)]

第一次

第一次握手:建立连接时,客户端发送syn包(seq=j)到服务器,并进入SYN_SENT状态,等待服务器确认;SYN:同步序列编号(Synchronize Sequence Numbers)。

第二次

第二次握手:服务器收到syn包,必须确认客户端的SYN(ack=j+1),同时自己也发送一个SYN包(seq=k),即SYN+ACK包,此时服务器进入SYN_RECV状态。 [3]

第三次

第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED(TCP连接成功)状态,完成三次握手。

完成三次握手,客户端与服务器开始传送数据,在上述过程中,还有一些重要的概念:

(1)未连接队列

三次握手协议中,服务器维护一个未连接队列,该队列为每个客户端的SYN包(seq=j)开设一个条目,该条目表明服务器已收到SYN包,并向客户发出确认,正在等待客户的确认包。这些条目所标识的连接在服务器处于 Syn_RECV状态,当服务器收到客户的确认包时,删除该条目,服务器进入ESTABLISHED状态。 [3]

(2)Backlog参数

三次握手协议

表示内核为相应套接字排队的最大连接个数。SYN-ACK重传次数服务器发送完SYN-ACK包,如果未收到客户确认包,服务器进行首次重传,等待一段时间仍未收到客户确认包,进行第二次重传,如果重传次数超过系统规定的最大重传次数,系统将该连接信息从半连接队列中删除。注意,每次重传等待的时间不一定相同。 [3]

(3)半连接存活时间

是指半连接队列的条目存活的最长时间,也即服务器从收到SYN包到确认这个报文无效的最长时间,该时间值是所有重传请求包的最长等待时间总和。有时我们也称半连接存活时间为Timeout时间、SYN_RECV存活时间。

四次挥手

断开连接的时候,需要经过四次挥手

  1. A 给B 发送消息需要断开连接
  2. B 给A 回消息 等一等
  3. B 给A 回消息 处理的工作已完成可以断开
  4. A 给B 回收到 断开连接

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fz2bSQDl-1681793689893)(网络编程.assets/d000baa1cd11728bf839be44c8fcc3cec3fd2cbb.png)]

对于一个已经建立的连接,TCP使用改进的四次挥手来释放连接(使用一个带有FIN附加标记的报文段)。TCP关闭连接的步骤如下:

第一步,当主机A的应用程序通知TCP数据已经发送完毕时,TCP向主机B发送一个带有FIN附加标记的报文段(FIN表示英文finish)。 [4]

第二步,主机B收到这个FIN报文段之后,并不立即用FIN报文段回复主机A,而是先向主机A发送一个确认序号ACK,同时通知自己相应的应用程序:对方要求关闭连接(先发送ACK的目的是为了防止在这段时间内,对方重传FIN报文段)。 [4]

第三步,主机B的应用程序告诉TCP:我要彻底的关闭连接,TCP向主机A送一个FIN报文段。 [4]

第四步,主机A收到这个FIN报文段后,向主机B发送一个ACK表示连接彻底释放。

为什么建立连接是三次握手,断开连接是四次挥手

答:因为当Server端收到Client端的SYN连接请求报文后,可以直接发送SYN+ACK报文。其中ACK报文是用来应答的,SYN报文是用来同步的。但是关闭连接时,当Server端收到FIN报文时,很可能并不会立即关闭SOCKET,所以只能先回复一个ACK报文,告诉Client端,“你发的FIN报文我收到了”。只有等到我Server端所有的报文都发送完了,我才能发送FIN报文,因此不能一起发送。故需要四步挥手。

udp协议

当使用udp协议的时候,如果A给B发送消息,B不会给出反馈,A不知道对方接收到没有,协议更快

URL

统一资源定位符

一个正确的url应该包含四个 部分

https://www.baidu.com:443/index.html
https://www.baidu.com
https 协议
www.baidu.com 主机
443 端口
index.html 资源位置

当输入一个URL在浏览器后,点击回车到页面完整显示,中间经历了什么?

当点击回车以后,首先确认传输协议,然后开始解析域名,首先在hosts文件中解析域名,如果解析成功则得到ip,直接去访问,如果没有解析成功则去dns服务器上解析域名,这里一般都能够解析成功,如果没有解析成功则提示无法访问。解析成功后通过路由器转发找到目标服务器,通过指定的端口进入目标服务器找到对应的资源,然后响应给浏览器显示出来。如果没有找到对应的资源则提示404。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oTg6Xya8-1681793689893)(网络编程.assets/image-20220307144754173.png)]

套接字(socket)

在java中实现网络编程主要通过socket来完成,前面所讲的所有内容,java都封装好了,我们只需要直接使用即可

单工

数据传输时单向的,不能逆向传输。比如:BB机,打印机

package com.zlt.socket20220307.simplex;

import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.Socket;

public class Client {

    public static void main(String[] args) {
        try {
            //对象创建后会自动去连接服务器
            Socket socket = new Socket("127.0.0.1",10000);
            //客户端连接服务器成功
            OutputStream outputStream = socket.getOutputStream();//客户端发送数据到服务器去就是输出
            OutputStreamWriter oow = new OutputStreamWriter(outputStream,"UTF-8");
            oow.write("你好服务器\n");//将数据发送出去
            oow.flush();//刷新流
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
package com.zlt.socket20220307.simplex;

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

public class Server {
    public static void main(String[] args) {
        ServerSocket serverSocket = null;
        try {
            serverSocket = new ServerSocket(10000);//创建一个服务器,监听9999端口
            //阻塞线程等待客户端的连接
            Socket accept = serverSocket.accept();//监听9999端口
            System.out.println("客户端连接成功");
            InputStream inputStream = accept.getInputStream();
            InputStreamReader isr = new InputStreamReader(inputStream,"UTF-8");
            BufferedReader br = new BufferedReader(isr);
            String s = br.readLine();
            System.out.println("客户端对服务器说:" + s);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

半双工

双向发送数据,但是不能同时进行,比如:对讲机

package com.zlt.socket20220307.halfduplex;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;

public class Server {
    public static void main(String[] args) {
        ServerSocket serverSocket = null;
        try {
            serverSocket = new ServerSocket(10000);//创建一个服务器,监听9999端口
            //阻塞线程等待客户端的连接
            Socket accept = serverSocket.accept();//监听9999端口
            System.out.println("客户端连接成功");
            while(true){
                //收消息
                InputStream inputStream = accept.getInputStream();
                InputStreamReader isr = new InputStreamReader(inputStream,"UTF-8");
                BufferedReader br = new BufferedReader(isr);
                String s = br.readLine();
                System.out.println("客户端对服务器说:" + s);
                //回消息
                OutputStream outputStream = accept.getOutputStream();//客户端发送数据到服务器去就是输出
                OutputStreamWriter oow = new OutputStreamWriter(outputStream,"UTF-8");
                Scanner scanner = new Scanner(System.in);
                System.out.println("请输入要对客户端说的内容");
                oow.write(scanner.nextLine() + "\n");//将数据发送出去
                oow.flush();//刷新流
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
package com.zlt.socket20220307.halfduplex;

import java.io.*;
import java.net.Socket;
import java.util.Scanner;

public class Client {
    public static void main(String[] args) {
        try {
            //对象创建后会自动去连接服务器
            Socket socket = new Socket("127.0.0.1",10000);
           while(true){
               //客户端连接服务器成功
               OutputStream outputStream = socket.getOutputStream();//客户端发送数据到服务器去就是输出
               OutputStreamWriter oow = new OutputStreamWriter(outputStream,"UTF-8");
               System.out.println("请输入要对服务器说的内容");
               oow.write(new Scanner(System.in).nextLine() + "\n");//将数据发送出去
               oow.flush();//刷新流
               //收消息
               //收消息
               InputStream inputStream = socket.getInputStream();
               InputStreamReader isr = new InputStreamReader(inputStream,"UTF-8");
               BufferedReader br = new BufferedReader(isr);
               String s = br.readLine();
               System.out.println("服务器对客户端说:" + s);
           }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

全双工

有两个通道,发送和接收数据互不影响,可以同时进行 比如:QQ

package com.zlt.socket20220307.fulldeplex;

import java.io.*;
import java.net.Socket;
import java.util.Scanner;

public class Client {
    public static void main(String[] args) {
        try {
            //对象创建后会自动去连接服务器
            Socket socket = new Socket("127.0.0.1",10000);
            Thread thread = new Thread(){
                @Override
                public void run() {
                    super.run();
                    while (true){
                        //收消息
                        //收消息
                        InputStream inputStream = null;
                        try {
                            inputStream = socket.getInputStream();
                            InputStreamReader isr = new InputStreamReader(inputStream,"UTF-8");
                            BufferedReader br = new BufferedReader(isr);
                            String s = br.readLine();
                            System.out.println("服务器对客户端说:" + s);
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
            };
            thread.start();
           while(true){
               //客户端连接服务器成功
               OutputStream outputStream = socket.getOutputStream();//客户端发送数据到服务器去就是输出
               OutputStreamWriter oow = new OutputStreamWriter(outputStream,"UTF-8");
               System.out.println("请输入要对服务器说的内容");
               oow.write(new Scanner(System.in).nextLine() + "\n");//将数据发送出去
               oow.flush();//刷新流
           }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
package com.zlt.socket20220307.fulldeplex;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;

public class Server {
    public static void main(String[] args) {
        ServerSocket serverSocket = null;
        try {
            serverSocket = new ServerSocket(10000);//创建一个服务器,监听9999端口
            //阻塞线程等待客户端的连接
            Socket accept = serverSocket.accept();//监听9999端口
            System.out.println("客户端连接成功");
            Thread thread = new Thread(){
                @Override
                public void run() {
                    super.run();
                    while (true){
                        //收消息
                        //收消息
                        InputStream inputStream = null;
                        try {
                            inputStream = accept.getInputStream();
                            InputStreamReader isr = new InputStreamReader(inputStream,"UTF-8");
                            BufferedReader br = new BufferedReader(isr);
                            String s = br.readLine();
                            System.out.println("客户端对服务器说:" + s);
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
            };
            thread.start();
            while(true){
                //回消息
                OutputStream outputStream = accept.getOutputStream();//客户端发送数据到服务器去就是输出
                OutputStreamWriter oow = new OutputStreamWriter(outputStream,"UTF-8");
                Scanner scanner = new Scanner(System.in);
                System.out.println("请输入要对客户端说的内容");
                oow.write(scanner.nextLine() + "\n");//将数据发送出去
                oow.flush();//刷新流
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员zhi路

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值