网络编程(UDP与TCP)

1.概念

什么是⽹络编程?
⽹络编程,指⽹络上的主机,通过不同的进程,以编程的⽅式实现⽹络通信(或称为⽹络数据传
输)。
发送端和接收端
在⼀次⽹络数据传输时:

发送端:数据的发送⽅进程,称为发送端。发送端主机即⽹络通信中的源主机。
接收端:数据的接收⽅进程,称为接收端。接收端主机即⽹络通信中的⽬的主机。
收发端:发送端和接收端两端,也简称为收发端。

请求和响应
⼀般来说,获取⼀个⽹络资源,涉及到两次⽹络数据传输:

• 第⼀次:请求数据的发送
• 第⼆次:响应数据的发送。

网络传输数据的基本单位;

1.数据报 Datagram UDP
2.数据段 Segment TCP
3.数据包 Packet IP
4.数据帧 Frame 数据链路层

客⼾端和服务端

服务端:在常⻅的⽹络数据传输场景下,把提供服务的⼀⽅进程,称为服务端,可以提供对外服务。
客⼾端:获取服务的⼀⽅进程,称为客⼾端。

常⻅的客⼾端服务端模型
最常⻅的场景,客⼾端是指给⽤⼾使⽤的程序,服务端是提供⽤⼾服务的程序:

  1. 客⼾端先发送请求到服务端
  2. 服务端根据请求数据,执⾏相应的业务处理
  3. 服务端返回响应:发送业务处理结果
  4. 客⼾端根据响应数据,展⽰处理结果(展⽰获取的资源,或提⽰保存资源的处理结果)

2.Socket套接字

概念

Socket套接字,是由系统提供⽤于⽹络通信的技术,是基于TCP/IP协议的⽹络通信的基本操作单元。基于Socket套接字的⽹络程序开发就是⽹络编程。

操作系统提供的socket API:
1.流式套接字----给TCP使用的
2.数据报套接字—给UDP使用的
3.Unix域套接字–不能跨主机通信,本地机进程与进程之间的通信方式
TCP和UDP都是传输层协议,都是给应用层提供服务的
TCP和UDP的特点:

TCP:有连接(打电话,通信双方保存对方的信息),可靠传输(可以尽量让数据完整发送给对方,小概率可能会丢包,保证了可靠效率就降低了),面向字节流(如文件操作就是字节流等等。。。),全双工(双向通信)
UDP:无连接(发短信,通信双方不保存对方的信息),不可靠传输(有概率丢包,这个效率高),面向数据报(一次读写只能读写一个完整的数据报(datagram)),全双工

3.UDP

UDP的socket api的两个类
1.DatagramSocket
DatagramSocket就是对于操作系统的Socket概念的封装(系统中的socket,可以理解为一种文件,socket文件就可以视为“网卡”这种硬件设备的抽象表现形式,针对socket文件进行读写操作就相当于针对网卡这个硬件设备进行读写)
总结:此处的DatagramSocket就是操作网卡的“遥控器”。
方法:
void receive(DatagramPacket p)
void send(DatagramPacket p)
void close() (socket也是一种文件,用完了要关闭,否则会占用文件描述符表的一个表项)
2.DatagramPacket
针对UDP数据报的抽象表示,一次发送/接受,就是以数据报为单位

整体流程是:
在这里插入图片描述

服务端

public class udpEchoserver {
    DatagramSocket datagramSocket=null;
    public udpEchoserver(int port) throws SocketException {
        datagramSocket=new DatagramSocket(port);
    }
    public void start() throws IOException {
        System.out.println("服务器启动");
        while (true){
            //1.接受客户端的请求
            DatagramPacket requestPacket=new DatagramPacket(new byte[4096],4096);
            datagramSocket.receive(requestPacket);
            String request=new String(requestPacket.getData(),0,requestPacket.getLength());
            //2.计算响应
            String response=process(request);
            //返回响应
            DatagramPacket responsePacket=new DatagramPacket(response.getBytes(),0,response.getBytes().length,requestPacket.getSocketAddress());
            datagramSocket.send(responsePacket);
            System.out.printf("[%s:%d] req=%s,resp=%s",requestPacket.getAddress(),requestPacket.getPort(),request,response);
        }
    }

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

    public static void main(String[] args) throws IOException {
        udpEchoserver udpEchoserver=new udpEchoserver(8156);
        udpEchoserver.start();
    }
}

客户端

public class udpEchoClient {
    DatagramSocket socket=null;
    String severIp;
    int port;
    public udpEchoClient(String severIp, int port) throws SocketException {
        socket=new DatagramSocket();
        this.severIp =severIp;
        this.port = port;
    }
    public void start() throws IOException {
        Scanner scanner=new Scanner(System.in);
        while (true){
            System.out.println("请输入发送的消息:");
            String request =scanner.next();
            DatagramPacket requestPacket=new DatagramPacket(request.getBytes(),request.getBytes().length,InetAddress.getByName(severIp),port);
            //给指定IP和端口号发送信息,InetAddress.getByName()方法是把点分十进制的转化成java能识别的32位二进制字符串(点分十进制是给人看的)
            socket.send(requestPacket);
            DatagramPacket severPacket=new DatagramPacket(new byte[4096],4096);
            socket.receive(severPacket);
            //客户端发送完后,这里会有短暂的阻塞,(把请求发出去响应回来时ms级,但是顺序执行是ns级)如果不阻塞这里执行啥东西都没。并且这里的阻塞功能api已经实现好了
            String response=new String(severPacket.getData(),0,severPacket.getLength());
            System.out.println(response);
        }


    }

    public static void main(String[] args) throws IOException {
       udpEchoClient udpEchoClient=new udpEchoClient("127.0.0.1",8156);
       udpEchoClient.start();
    }
}

在这里插入图片描述
实现本机间的交互

如何启动多个客户端?
在这里插入图片描述
实现多个客户端对服务器进行交互

注意,上述如果将ip改为你女朋友的IP除非连着同一个wife(局域网内),将代码客户端代码给女朋友能实现相互交互,否则不能进行非局域网的传输,那么如何实现任何人都能连上我们的服务器呢?这就需要一个公网IP,租一个云服务器

在所有IP地址中:
这三种情况是私网IP,剩下的都是公网IP

1)10.*
2)172.16-172.31.*
3)192.168.*

TCP套接字

API 介绍
ServerSocket
ServerSocket 是创建TCP服务端Socket的API。
ServerSocket 构造⽅法:

服务端

public class TcpEchoSever {
    ServerSocket serverSocket=null;

    public TcpEchoSever(int port) throws IOException {
            serverSocket = new ServerSocket(port);
    }
    public void start() throws IOException {
        System.out.println("服务器启动");
        while(true){
            Socket clientSocket=serverSocket.accept();
            //与客户端建立联系
            processConection(clientSocket);
        }
    }

    private void processConection(Socket clientSocket) throws IOException {
        System.out.printf("[%s,%d]客户端上线",clientSocket.getInetAddress(),clientSocket.getPort());
        try(InputStream inputStream=clientSocket.getInputStream();
            OutputStream outputStream=clientSocket.getOutputStream()) {
            Scanner scanner=new Scanner(inputStream);
            while(true){
                if(!scanner.hasNext()){
                    System.out.printf("[%s:%d]读取完毕,客户端下线",clientSocket.getInetAddress(),clientSocket.getPort());
                    break;
                }
                String request=scanner.next();
                String response=process(request);
                outputStream.write(response.getBytes(),0,response.getBytes().length);
                System.out.printf("[%s:%d] req=%s resp=%s",serverSocket.getInetAddress(),serverSocket.getLocalPort(),request,response);
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }finally {
            clientSocket.close();
        }
    }

    private String process(String request) {
        return request+"\n";
    }

    public static void main(String[] args) throws IOException {
        TcpEchoSever tcpEchoSever=new TcpEchoSever(9090);
        tcpEchoSever.start();
    }
}

服务端

public class TcpEchoClient {
    Socket socket=null;

    public TcpEchoClient(String severIp,int serverPort) throws IOException {
        socket=new Socket(severIp,serverPort);
    }
    public void start() throws IOException {
        System.out.println("客户端启动");
        Scanner scannerConsole=new Scanner(System.in);
        try(InputStream inputStream=socket.getInputStream(); OutputStream outputStream=socket.getOutputStream()){
            Scanner scannerNetWork=new Scanner(inputStream);
            while (true){
                System.out.println("请输入要发送的数据:");
                String request= scannerConsole.next();
                request+="\n";
                outputStream.write(request.getBytes());
                if(!scannerConsole.hasNext()){
                    break;
                }
                String response=scannerNetWork.next();
                System.out.println(response);
            }


        }catch (IOException e){
            e.printStackTrace();
        }
    }

    public static void main(String[] args) throws IOException {
      TcpEchoClient tcpEchoClient=new TcpEchoClient("127.0.0.1",9090);
      tcpEchoClient.start();
    }
}

  • 16
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值