首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >【Java EE初阶 --- 网络原理】网络编程

【Java EE初阶 --- 网络原理】网络编程

作者头像
optimistic_chen
发布2026-01-14 20:19:18
发布2026-01-14 20:19:18
850
举报

前言

在上篇博客提到网络的发展史,我们知道实现网络通信的原理,那么实现网络通信能给人类发展带来怎么样的驱动力呢?这篇博客将带了解网络通信的最大优势,网络编程带来的丰富的网络资源。

网络编程原理

⽹络编程:指⽹络上的主机,通过不同的进程,以编程的⽅式实现⽹络通信(或称为⽹络数据传输)

因为应用层要把数据交给传输层,传输层就提供了一个接口socket,这个接口是程序员关注的重中之重;至于更底层的数据链路层的接口,我们基本不关心,它们基本都是操作系统实现完成的。 而在传输层中有两个核心协议:TCP/UDP

协议

TCP

有连接

可靠传输

面向字节流

全双工

UDP

无连接

不可靠传输

面向数据报

全双工

· 有无连接,指的是一个抽象概念,逻辑上有无连接,也就是说,双方主机都保存在对方的信息 · 是否可靠传输,网络传输中,数据是非常容易出现丢失的情况,因为光电信号容易抽到外界干扰。可靠传输只是尽可能的提高传输成功的概率,不可靠传输把数据一发就不再管了。 · 面向字节流,读写数据时,以字节为单位;面向数据报, 读写数据时,以一个数据报为单位。 · 全双工支持双向通信(能读也能写);半双工,只支持单向通信(要么读要么写) 网卡是由Socket文件操作,所以操作网卡和操作普通文件差不多;Socket文件就相当于“网卡的遥控器”

UDP Socket编程准备

DatagramSocket是UDP Socket,用于 发送和接收UDP数据报(工具)

打开文件

方法名

DatagramSocket()

创建⼀个UDP数据报的Socket,绑定到本机任意⼀个随机端⼝(⼀般⽤于客⼾端)

DatagramSocket(int port)

创建⼀个UDP数据报的Socket,绑定到本机指定的端⼝(⼀般⽤于服务端)

读写文件

方法名

void receive(DatagramPacket p )

从此套接字接收(读)数据报(如果没有接收到数据报,该⽅法会阻塞等待)

void send(DatagramPacket p)

从此套接字发送(写)数据报(不会阻塞等待,直接发送)

关闭文件

方法名

void close()

关闭此数据报套接字

DatagramPacket 是UDP Socket(单位),是 发送和接收的数据报(数据)

构造方法

DatagramPacket(byte[] buf, int length)

构造⼀个DatagramPacket以⽤来接收数据报,接收的数据保存在字节数组(第⼀个参数buf)中,接收指定⻓度(第⼆个参数length)

DatagramPacket(byte[] buf, int offset, int length,SocketAddress address)

构造⼀个DatagramPacket以⽤来发送数据报,发送的数据为字节数组(第⼀个参数buf)中,从0到指定⻓度(第⼆个参数length)。address指定⽬的主机的IP和端⼝号

方法

InetAddress getAddress()

从接收的数据报中,获取发送端主机IP地址;或从发送的数据报中,获取接收端主机IP地址

int getPort()

从接收的数据报中,获取发送端主机的端⼝号;或从发送的数据报中,获取接收端主机端⼝号

服务端
代码语言:javascript
复制
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
import java.nio.charset.StandardCharsets;

public class UdpEchoServer {
    private DatagramSocket socket=null;

    public UdpEchoServer(int port) throws SocketException {
        //指定端口号,让服务器使用
        socket=new DatagramSocket(port);//socket对象代表网卡对象
        //读文件代表从网卡收数据,写文件代表从网卡发数据
    }

    public  void start() throws IOException {
        System.out.println("启动服务器");
        while(true){
            //循环一次相当于处理一次请求

            //DatagramPacket表示一个UDP数据报,此处传入字节数组
            DatagramPacket requestpacket=new DatagramPacket(new byte[4096],4096);

            //1.读取请求并解析
            socket.receive(requestpacket);//输出型参数
            //将读取到的二进制数据转换为字符串
            String request=new String(requestpacket.getData(),0,requestpacket.getLength());

            //2.根据请求,计算响应(此处为回显服务器)
            String response=process(request);

            //3.把响应返回给客户端
            //根据request构造 DatagramPacket,发送给客户端
            DatagramPacket responsePacket=new DatagramPacket(response.getBytes(),response.getBytes().length,
            requestpacket.getAddress(),requestpacket.getPort());
            //此时UPD协议无连接,没有保存客户端信息,还不知道发给谁
            //还需要知道目的IP和目的端口号
            socket.send(responsePacket);
            System.out.printf("[%s:%d] req:%s,resp:%s\n",requestpacket.getAddress().toString(),requestpacket.getPort(),
                    request,response);
        }
    }

    private String process(String request){
        return request;
    }

    public static void main(String[] args) throws IOException {
        UdpEchoServer server=new UdpEchoServer(9090);
        server.start();
    }
}
在这里插入图片描述
在这里插入图片描述
客户端
代码语言:javascript
复制
import java.io.IOException;
import java.net.*;
import java.sql.SQLOutput;
import java.util.Scanner;

public class UdpEchoClient {
    private DatagramSocket  socket = null;
    private String serverIP;
    private int serverPort;
    //客户端,构造方法要指定访问服务区的地址和端口号
    public UdpEchoClient(String serverIP,int serverPort) throws SocketException {
        this.serverIP=serverIP;
        this.serverPort=serverPort;
        socket=new DatagramSocket();
    }

    public void start() throws IOException {
        while(true){
            //客户端输入数据
            Scanner scanner=new Scanner(System.in);
            System.out.println("请输入要发送的内容");
            if(!scanner.hasNext()){
                break;
            }
            String request=scanner.next();

            //把数据发给服务器,要构造DatagramPacket对象
            //不但要构造数据,也要设置好服务器的IP和端口号
            DatagramPacket requestPacket=new DatagramPacket(request.getBytes(),request.getBytes().length,
                    InetAddress.getByName(serverIP),serverPort);

            //发送数据
            socket.send(requestPacket);

            //接收服务器的响应
            DatagramPacket responsePacket=new DatagramPacket(new byte[4096],4096);
            socket.receive(responsePacket);

            //日志
            String response=new String(responsePacket.getData(),0,responsePacket.getLength());
            System.out.println(response);
        }

    }

    public static void main(String[] args) throws IOException {
        UdpEchoClient client=new UdpEchoClient("127.0.0.1",9090);
        client.start();
    }
}
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

TCP Socket编程准备

TCP核心就是面向字节流,读写的基本单位就是字节byte ServerSocket是创建 TCP 服务端 Socket 的接口

构造方法

ServerSocket(int port)

创建一个服务端Socket,并指定端口号

普通方法

Socket accept()

联通连接的关键操作

void close()

关闭套接字

Socket是客户端Socket,或者服务端接收到客户端建立连接的请求后,返回服务端Socket.但是无论是客户端还是服务端,都是双方建立联系以后,保存对端信息,与对方接收发数据的

构造方法

Socket(String host,int port)

创建一个客户端Socket,并与对应IP的主机上,对应端口的进程建立联系

普通方法

InetAddress getInetAddress()

返回Socket连接地址

InetStream getInputStream()

返回Socket输入流(读)

InetStream getOutputStream()

返回Socket输出流(写)

服务端
代码语言:javascript
复制
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;

public class TcpEchoServer {
    private ServerSocket serversocket=null;

    public TcpEchoServer(int port) throws IOException {
        serversocket=new ServerSocket(port);
    }

    public void start() throws IOException {
        System.out.println("启动服务器");
        while(true){
            //TCP先处理客户端发来的连接
            Socket clientSocket=serversocket.accept();
            processConnection(clientSocket);
        }
    }
    private void processConnection(Socket clientSocket){
        System.out.printf("[%s:%d]客户端上线\n",clientSocket.getInetAddress(),clientSocket.getPort());
        try(InputStream inputStream=clientSocket.getInputStream();
            OutputStream outputStream=clientSocket.getOutputStream()) {
            Scanner scanner=new Scanner(inputStream);
            PrintWriter writer=new PrintWriter(outputStream);
            while(true){
                //读取请求
                if(!scanner.hasNext()) {
                    System.out.printf("[%s:%d]客户端下线\n",clientSocket.getInetAddress(),clientSocket.getPort());
                    break;
                }
                String request=scanner.next();
                //根据请求计算响应
                String response=process(request);
                //返沪响应到客户端
                writer.println(response);
                writer.flush();

                System.out.printf("[%s:%d] req:%s,resp:%s\n",clientSocket.getInetAddress(),clientSocket.getPort(),
                        request,response);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    private String process(String request){
        return request;
    }

    public static void main(String[] args) throws IOException {
        TcpEchoServer server=new TcpEchoServer(9090);
        server.start();
    }
}
客户端
代码语言:javascript
复制
import jdk.jshell.SourceCodeAnalysis;

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

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()){
            Scanner scanner1=new Scanner(inputStream);
            PrintWriter writer=new PrintWriter(outputStream);

            while(true){
                //输入数据
                String request=scanner.next();
                //发送给服务器
                writer.println(request);//这里只是把数据发送到“发送缓冲区(内存)”,没有到网卡
                writer.flush();//刷新缓冲区
                //读取服务器返回的响应
                String response=scanner1.next();
                //打印
                System.out.println(response);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    public static void main(String[] args) throws IOException {
        TcpEchoClient client=new TcpEchoClient("127.0.0.1",9090);
        client.start();
    }
}
多个客户端同时发起请求

面对多个客户端同时给服务器发送请求,我们要求第一时间响应,也就是说服务端要同时回应多个请求,那就刚好用到了多线程的理念,多个线程解决多个客户端请求。

首先,我们使服务器只要接收到请求,就去创建一个线程,响应请求

代码语言:javascript
复制
public void start() throws IOException {
     System.out.println("服务器启动!");
     while (true) {
        Socket clientSocket = serversocket.accept();
        Thread t = new Thread(() -> {
           processConnection(clientSocket);
        });
        t.start();
    }
}

但是呢,如果有超级多的客户端发起请求,难道我们要创建同样多的线程吗?这种方法太浪费CPU资源,为了避免巨大的资源开销,可以引入线程池

代码语言:javascript
复制
public void start() throws IOException {
     System.out.println("服务器启动!");
     ExecutorService service = Executors.newCachedThreadPool();
     while (true) {
        Socket clientSocket = serversocket.accept();
        service.submit(new Runnable() {
            @Override
            public void run() {
                 processConnection(clientSocket);
            }
        });
    }
}

完结

可以点一个免费的赞并收藏起来~ 可以点点关注,避免找不到我~ ,我的主页:optimistic_chen 我们下期不见不散 ~ ~ ~

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2026-01-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 网络编程原理
    • UDP Socket编程准备
      • 服务端
      • 客户端
    • TCP Socket编程准备
      • 服务端
      • 客户端
      • 多个客户端同时发起请求
  • 完结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档