• java网络编程


    1. IP、域名、端口号的概念

    1.1 IP

    IP(Internet Protocol)是互联网的基础协议,其中一个作用就是给互联网中的设备(主机)分配IP地址,以便在互联网中找到某个设备

    以127开头的IP地址称为本地回环地址,比如127.0.0.1 ,表示本机IP地址,主要作用是方便进行本地测试

    数据包是互联网中数据传输的基本单位,IP规定了数据如何分段打包,以及单个数据包如何传输到目标主机,以便各种设备之间可以相互交换数据

    1.2 域名

    IP地址不方便记忆,而域名(Domain Name),是互联网上主机的名称,每个域名都对应了一个IP地址,而且域名方便记忆,所以人们一般使用域名访问某台主机

    localhost表示本地主机的名称,对应127.0.0.1

    DNS(Domain Name System),即域名系统,存放着互联网上所有域名和IP地址的对应关系,当人们使用域名时,就需要先通过DNS查询域名对应的IP地址,然后再使用IP地址找到目标主机

    计算机中的hosts文件是一个本地的DNS(C:WindowsSystem32driversetc目录下),我们可以修改hosts文件手动配置域名和IP地址的对应关系,计算机在查找时会优先查找hosts文件

    1.3 端口号

    一台主机可以提供多种服务(运行多个程序),为了方便外界区分和访问,每个服务都要有一个端口号,通过IP地址和端口号来唯一确定某台主机上的某个服务

    端口号的范围是 [ 0 , 65535 ] ,其中 [ 0 , 1023 ] 是系统保留端口,提供给系统服务以及其他著名的服务如HTTP(80)。我们自己的程序如果不提供著名服务,就尽量不要占用系统保留端口

    主机中某个端口号某个时刻只能被一个程序占用,系统采用先申请先得的方式进行分配,程序结束即释放所占用的端口号

    某个端口号有时候会被其他程序占用,或者程序重复启动时也会报端口号被占用的错误,这时可以在cmd命令行执行netstat  -ano 查看占用某个端口号的程序的进程id,然后到任务管理器中找到该进程结束掉即可

    2. TCP

    TCP(Transmission Control Protocol)传输控制协议,是一个面向连接的,可靠的,基于字节流的传输层通信协议,很多应用层协议都建立在TCP之上,程序也可直接使用TCP进行网络通信。

    TCP会在两台主机之间建立一个连接(虚拟的),通过一定的方式控制数据传输的过程,可以保证数据的完整、有序、正确

    3. Socket编程

    网络编程,主要是指基于TCP的网络通信编程,使用Socket类实现,也称为socket编程

    socket编程模型中有服务器端和客户端,服务器端使用ServerSocket创建,一般有固定的IP地址和端口号,方便向外界提供服务。客户端可以有多个,并且使用Socket主动连接服务器。连接后,服务器端也创建一个Socket对象表示这次连接

     

    编程步骤:

    服务器端:

    1 创建服务器对象ServerSocket

    2 等待客户端的连接请求,收到请求后即返回表示这次连接的Socket对象

    3 开启新的线程专门处理这个连接

    4 获得连接的输入输出流,并按照一定的规则进行数据交换

    5 关闭连接(关闭连接时会自动关闭IO流)

    客户端:

    1 创建Socket对象,即向服务器申请连接

    2 获得连接的输入输出流,并按照一定的规则进行数据交换

    3 最后关闭连接(关闭连接时会自动关闭IO流)

    平时编程时一般都是基于应用层协议,比如HTTP,直接进行socket编程的并不多。但由于socket编程属于基础层面的重要技术,要求务必掌握

    public class Server1 {
    
        public static void main(String[] args) throws IOException {
    
            ServerSocket server = new ServerSocket(10001);
            Socket socket = server.accept();
    
            InputStream inputStream = socket.getInputStream();
            OutputStream outputStream = socket.getOutputStream();
    
            byte[] data = "hello".getBytes();
            outputStream.write(data);
    
            socket.close();
        }
    }
    public class Client1 {
    
        public static void main(String[] args) throws IOException {
    
            Socket socket = new Socket("localhost", 10001);
    
            InputStream inputStream = socket.getInputStream();
            OutputStream outputStream = socket.getOutputStream();
    
            byte[] buff = new byte[1024];
            int len = inputStream.read(buff);
            System.out.println(new String(buff, 0, len));
            socket.close();
        }
    }

     执行步骤:

    1.运行Server1

    2.运行Client1

    3.输出

    hello
    

    3.1 基于Socket实现字符串翻转服务器

    /*
     *  把从客户端读取到的一行数据的字符进行翻转,然后发送给客户端
     *  当读取到over时,连接断开
     */
    public class Server2 {
    
        public static void main(String[] args) {
    
            try {
                ServerSocket server = new ServerSocket(10002);
    
                while (true) {
                    Socket socket = server.accept();
                    MyThread myThread = new MyThread(socket);
                    myThread.start();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    
    class MyThread extends Thread {
        private Socket socket;
    
        public MyThread(Socket socket) {
            this.socket = socket;
        }
    
        @Override
        public void run() {
            try {
                BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
                String line = null;
                while ((line = bufferedReader.readLine()) != null) {
                    if ("over".equalsIgnoreCase(line)) {
                        break;
                    }
    
                    //字符翻转的操作
                    char[] chs = line.toCharArray();
    
                    for (int i = 0; i < chs.length / 2; i++) {
                        char ch = chs[i];
                        chs[i] = chs[chs.length - 1 - i];
                        chs[chs.length - 1 - i] = ch;
                    }
    
                    bufferedWriter.write(chs);
                    bufferedWriter.newLine();
                    bufferedWriter.flush();
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
    
        }
    }
    View Code-字符串翻转服务端
    public class Client2 {
        public static void main(String[] args) {
            Socket socket = null;
            Scanner scanner = null;
            try {
                socket = new Socket("localhost", 10002);
                BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
    
                scanner = new Scanner(System.in);
                String line = null;
                while ((line = scanner.nextLine()) != null) {
                    bufferedWriter.write(line);
                    bufferedWriter.newLine();
                    bufferedWriter.flush();
                    line = bufferedReader.readLine();
                    if (line == null) {
                        break;
                    }
                    System.out.println(line);
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                try {
                    if (socket != null) {
                        socket.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
                if (scanner != null) {
                    scanner.close();
                }
            }
        }
    }
    View Code-字符串翻转客户端

    4. 基于UDP的网络编程

    传输层协议除了TCP,还有UDP(User Datagram Protocol),即用户数据报协议。UDP是无连接的,而且不保证数据的完整、有序,但传输效率非常高,适合视频、音频等对数据可靠性要求不太高的场景

    UDP编程的时候没有典型的服务器——客户端结构,而且通信的两端不建立连接,可以直接把数据封装成数据包发送到另一端,而且每一端都可以发送、接收数据包

    DatagramSocket 表示通信的一端,可以发送、接收数据包

    DatagramPacket 数据包,理论上一个数据包可包含的数据量最多为65535字节

    public class Send1 {
    
        public static void main(String[] args) throws IOException {
            DatagramSocket sendSocket = new DatagramSocket(10003);
            byte[] data = "hello".getBytes();
            DatagramPacket packet = new DatagramPacket(data, data.length, InetAddress.getLocalHost(), 10004);
            sendSocket.send(packet);
            sendSocket.close();
        }
    }
    View Code-send1
    public class Receive1 {
    
        public static void main(String[] args) throws IOException {
            DatagramSocket receiveSocket = new DatagramSocket(10004);
            byte[] buff = new byte[1024];
            DatagramPacket packet = new DatagramPacket(buff, buff.length);
            receiveSocket.receive(packet);
            int len = packet.getLength();
            System.out.println(new String(buff, 0, len));
            receiveSocket.close();
        }
    }
    View Code-received
  • 相关阅读:
    oracle参数文件(1)
    提高HTML5 canvas性能的几种方法(转)
    基于TouchVG开发的Windows矢量图形编辑器
    使用rapidjson实现了TouchVG的序列化适配器类
    关于用例的几个问题分析
    重温《UML风格》
    API设计准则(转)
    UML初级培训录音内容
    暂定的UML培训大纲
    基于Android平台多个Icon的APk——实现多程序入口总结(转)
  • 原文地址:https://www.cnblogs.com/renjing/p/socket.html
Copyright © 2020-2023  润新知