udp和tcp

udp服务器和tcp服务器.
udp服务器按照数据报的形式发送,数据包即字节数组,然后经过五层协议在网络上进行传输.
tcp服务器面向字节流,也即字符串,规定收发双发的数据必须相同,所以一般是按行读取和发送.
tcp服务器执行过程:
1.首先建立连接,通过实例化一个Socket对象(即网卡)实现.其中内核会自动通过三次握手建立连接,建立连接是保证客户端和服务器端的收发能力正常.
2.建立连接后内核将Socket放入阻塞队列,然后服务器端通过accept方法取出连接,对连接进行处理,相当于打电话,一个人和另外几个人拨通电话,然后按照这几个人的先后顺序一个一个进行通话交流,但是这种方式只能一次处理一个连接,所以用多线程并发机制可以实现多个连接并发处理.
3.处理过程包括长连接和短连接,长连接是指一个连接中会有很多次交互,一般通过循环实现,短连接是指只能有一次交互.连接终止的时候客户端会先终止,然后服务器端才会终止,服务器为客户端服务.
当客户端和服务器端在收发过程中时,如果一方没有发送数据,则另一方会阻塞,知道另一方发送数据为止.
注意:在发送后,要进行flush操作,这是因为数据发送之前放到了内存中的缓冲区里,而最终需要经过数据链路层的网卡进行发送,flush操作会将缓冲区的数据放到网卡中,由网卡给数据加上mac地址,封装成帧,然后再由物理层转换为光电信号在网络介质中进行传输.如果不进行flush操作,则数据就会一直停留在缓冲区里,不会放到网卡中.另外,udp是自动随机将寻找mac路径,但是tcp已经建立连接,不用再寻找路径,直接用之前的就可以.
用tcp服务器实现简单的回显服务器.
**tcp:**客户端:

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.Buffer;

/**
 * @author :liuheizi
 * @date :Created in 2022/2/5 15:09
 * @description:TCP代码
 * @modified By:
 * @version: 1.8.0_192
 */
class EchoSever {
    private ServerSocket serverSocket=null;

    public EchoSever(int port) throws IOException {
        this.serverSocket = new ServerSocket(port);
    }

    public void start() throws IOException {
        System.out.println("服务器启动");
        while (true) {
            Socket socket = serverSocket.accept();
            poccess(socket);
        }

    }

    public void poccess(Socket n) {
        System.out.println("客户端端口号:" + n.getInetAddress().toString());
        System.out.println("客户端端口号:" + n.getPort());
        try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(n.getInputStream()));
             BufferedWriter bufferedWriter=new BufferedWriter(new OutputStreamWriter(n.getOutputStream()))
        ) {
            while (true) {
                String request = bufferedReader.readLine();
                String response = poccess1(request);
                bufferedWriter.write(response+"\n");
                bufferedWriter.flush();
            }

        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("客户端退出");
        }
    }


    public String poccess1(String request) {
    return request;
    }
}
public class Mytest {
    public static void main(String[] args) throws IOException {
        EchoSever myServer = new EchoSever(9090);
        myServer.start();
    }
}

tcp客户端:

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

/**
 * @author :liuheizi
 * @date :Created in 2022/2/5 15:56
 * @description:
 * @modified By:
 * @version: 1.8.0_192
 */
class EchoClient1 {
    private Socket socket;

    public EchoClient1(String serverIp, int serverPort) throws IOException {
        this.socket = new Socket(serverIp, serverPort);
    }
    public void start() {
        Scanner scanner = new Scanner(System.in);

        try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
             BufferedWriter bufferedWriter=new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()))
        ) {
            while (true) {
                System.out.println("请输入");
                String request = scanner.nextLine();
                if ("exit".equals(request)) {
                    break;
                }
                bufferedWriter.write(request+"\n");
                bufferedWriter.flush();
                String response=bufferedReader.readLine();
                System.out.println(response);
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
public class MyClientTest {
    public static void main(String[] args) throws IOException {
        EchoClient1 echoClient = new EchoClient1("127.0.0.1",9090);
        echoClient.start();
    }
}

缓冲区的几种情况:
1.tcp服务器
2.文件传输(io流)
3.从控制台读取和打印

并发处理的服务器端代码:

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.Buffer;

/**
 * @author :liuheizi
 * @date :Created in 2022/2/5 15:09
 * @description:TCP代码
 * @modified By:
 * @version: 1.8.0_192
 */
class EchoSever {
    private ServerSocket serverSocket=null;

    public EchoSever(int port) throws IOException {
        this.serverSocket = new ServerSocket(port);
    }

    public void start() throws IOException {
        System.out.println("服务器启动");
        **while (true) {
            Socket socket = serverSocket.accept();
            Thread t1=new Thread(){
                @Override
                public void run() {
                    poccess(socket);
                }
            };
            t1.start();
        }** 

    }

    public void poccess(Socket n) {
        System.out.println("客户端端口号:" + n.getInetAddress().toString());
        System.out.println("客户端端口号:" + n.getPort());
        try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(n.getInputStream()));
             BufferedWriter bufferedWriter=new BufferedWriter(new OutputStreamWriter(n.getOutputStream()))
        ) {
            while (true) {
                String request = bufferedReader.readLine();
                String response = poccess1(request);
                bufferedWriter.write(response+"\n");
                bufferedWriter.flush();
            }

        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("客户端退出");
        }
    }


    public String poccess1(String request) {
    return request;
    }
}
public class Mytest {
    public static void main(String[] args) throws IOException {
        EchoSever myServer = new EchoSever(9090);
        myServer.start();
    }
}

实现服务器的关键是通过请求计算响应,也就是上图中的pocces1函数.
udp实现回显服务器
服务器端:

import javax.xml.crypto.Data;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;

/**
 * @author :liuheizi
 * @date :Created in 2022/2/5 15:56
 * @description:
 * @modified By:
 * @version: 1.8.0_192
 */
public class UdpEchoSever {
    private DatagramSocket datagramSocket;

    public UdpEchoSever(int port) throws SocketException {
        this.datagramSocket = new DatagramSocket(port);
    }
    public void start() throws IOException {
        System.out.println("服务器启动");
        while (true) {
            DatagramPacket requestPacket = new DatagramPacket(new byte[4096], 4096);
            datagramSocket.receive(requestPacket);
            String request = new String(requestPacket.getData(),0,requestPacket.getLength()).trim();
            String response = poccess(request);
            DatagramPacket responsePacket=new DatagramPacket(response.getBytes(),response.getBytes().length,
                    requestPacket.getSocketAddress());
            datagramSocket.send(responsePacket);
            System.out.println("客户端ip:" + requestPacket.getAddress());
            System.out.println("客户端端口号:"+requestPacket.getPort());
        }
    }
        public String poccess(String request){
            return request;
        }

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

客户端:

import javax.xml.crypto.Data;
import java.io.IOException;
import java.net.*;
import java.util.Scanner;

/**
 * @author :liuheizi
 * @date :Created in 2022/2/5 19:48
 * @description:
 * @modified By:
 * @version: 1.8.0_192
 */
public class UdpEchoClient {
   private DatagramSocket datagramSocket;
   private String severIp;
   private int severPort;

    public UdpEchoClient(String severIp, int severPort) throws SocketException {
        this.datagramSocket = new DatagramSocket();
        this.severIp=severIp;
        this.severPort = severPort;
    }
    public void start() throws IOException {
        Scanner scanner = new Scanner(System.in);
        System.out.println("服务器启动");
        while (true) {
            System.out.println("请输入");
            String request=scanner.nextLine();
            if ("exit".equals(request)) {
                break;
            }
            DatagramPacket requestPacket=new DatagramPacket(request.getBytes(),request.getBytes().length,
                    InetAddress.getByName(severIp),severPort);
            this.datagramSocket.send(requestPacket);
            DatagramPacket responsePacket = new DatagramPacket(new byte[4096], 4096);
            datagramSocket.receive(responsePacket);
            String response = new String(requestPacket.getData(),0,requestPacket.getLength()).trim();
            System.out.println(response);
        }
    }
    public static void main(String[] args) throws IOException {
        UdpEchoClient udpEchoClient = new UdpEchoClient("127.0.0.1", 9090);
        udpEchoClient.start();
    }

}
比较:
udp效率更高,因为不用建立连接,但是数据的安全性不高,容易丢失;tcp数据安全性高,但是效率低,因为需要需要频繁的建立连接和销毁连接.
udp代码比较繁琐,但是原理简单,即字节数组传输,tcp代码简单,但原理比较复杂,需要建立连接.
udp可以多个客户端访问,表现为哪个客户端给服务器发送数据了,服务器就接收数据并处理返回,此处是没有并发的,而不是向tcp那样一个一个客户端进行处理,tcp解决这个问题是通过并发线程.
多个客户端访问同一个服务器怎样简单实现?
通过xshell窗口,Java 包.类命令:
udp和tcp
快捷键:shift加右键

上一篇:Elasticsearch RestHighLevelClient --(八)


下一篇:ansible-playbook filter过滤器使用