Java进阶学习之网络编程(4)


《计算机网络》作为计算机专业的必修课,估计大家对他仍有后怕,这本书很厚,知识面很广,建议有时间的朋友通篇阅读和理解。

1.网络编程概述

1.1.目的

通过通信线路将多台计算机连接起来,并进行数据传输。

1.2.常用的网络协议

1.2.1.TCP

TCP(Transmission Control Protocol):传输控制协议,是一种面向连接、可靠的、基于字节流的传输层通讯协议。

TCP的三次握手
SYN:同步序列编号Synchronize Sequence Numbers
ACK:确认字符Acknowledge character

  1. 第一次握手:A的TCP客户端首先创建传输控制块TCB,然后向B发送连接请求报文段(SYN=1,seq=x),A进入SYN-SENT状态;
  2. 第二次握手:B收到连接请求报文后,如同意建立连接,则向A发送确认(SYN=1,ACK=1,确认号ack=x+1,seq=y),B进入SYN-RCVD状态;
  3. 第三次握手:A收到B的确认后,向B发出确认报文(ACK=1,确认号ack=y+1,seq=x+1),A进入ESTABLISHED,B收到A的确认后也进入ESTABLISHED。

TCP四次挥手
MSL:报文最大存活时间

  1. A向B发送连接释放报文段(FIN=1,seq=u),并停止再发送数据,主动关闭TCP连接,进入FIN-WAIT-1状态,等待B的确认;
  2. B收到后发出确认报文段(ACK=1,ack=u+1,seq=v),B进入CLOSE-WAIT状态,此时TCP连接处于半关闭状态,A到B的连接释放;
  3. A收到B的确认后,进入FIN-WAIT-2状态,等待B发出连接释放报文;
  4. B没有向A发出数据,B发出连接释放报文(FIN=1,ACK=1,seq=w,ack=u+1),B进入TIME-WAIT状态,等待A确认;
  5. A收到B的连接释放报文后,发出确认报文(ACK=1,seq=u+1,ack=w+1),A进入TIME-WAIT状态,此时TCP未释放掉,经过时间等待计数器设置的时间2MSL后,A进入CLOSED状态。
1.2.2.UDP

UDP(User Datagram Protocol):用户数据报协议,是一种无连接的传输协议。
特点:

  • 不可靠的协议,不建立连接,不进行数据检查,不等待应答,导致可能会出现数据丢失等现象
  • 报头很短,开销很小
  • 有较好的实用性,传输效率很高,受软件性能、带宽、收发端主机性能限制

2.Socket网络编程

2.1.Socket是什么

套接字Socket就是双向通信中一端的抽象。
Socket由IP地址和端口port确认。

2.2.Socket工作流程

  1. 服务器开启监听
  2. 客户端请求连接
  3. 确认连接

2.3.案例

服务端编写:

public class MyServer extends Thread {

    private ServerSocket serverSocket;

    public MyServer(int port) throws IOException {
        serverSocket = new ServerSocket(8888);
        System.out.println("服务端已启动,监听端口:" + serverSocket.getLocalPort());
    }

    @Override
    public void run() {
        Socket server = null;
        OutputStream os = null;
        DataOutputStream dos = null;
        while (true) {
            try {
                server = serverSocket.accept();
                System.out.println(server.getRemoteSocketAddress() + "连接成功!");
                os = server.getOutputStream();
                dos = new DataOutputStream(os);
                dos.writeUTF("hello!");
                dos.flush();

                dos.close();
                os.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        try {
            Thread t = new MyServer(8888);
            t.run();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

客户端编写:

public class MyClient {
    public static void main(String[] args) {
        Socket client = null;
        InputStream is = null;
        DataInputStream dis = null;
        try {
            client = new Socket("127.0.0.1", 8888);
            is = client.getInputStream();
            dis = new DataInputStream(is);
            System.out.println(dis.readUTF());

            dis.close();
            is.close();
            client.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

然后按照Socket工作流程,先启动服务点监听,执行结果:

启动客户端进行连接,执行结果:

连接成功后,接收到服务端发来的字符串"hello!"
看一下服务端有什么变化:

由于服务端是个死循环对8888端口进行监听,我们启动客户端多次看看服务端有什么变化:

posted @ 2022-12-01 10:39  liquorppp  阅读(20)  评论(0编辑  收藏  举报