网络编程

一、什么是网络

由点和线组成,表示多个对象之间的相互联系。

二、计算机网络

多台计算机之间相互联系,通过通信线路连接,作用是实现资源共享和信息传递。

互联网:指计算机之间相互连接,少量连接叫做局域网,俗称内网。

万维网:世界上所有的计算机相互连接的网络。俗称外网。

物联网:万物互联。指将普通的事物也通过手段连入到互联网中。

三、网络编程

网络编程实现计算机之间的连接和通信。

四、网络模型(OSI模型)

应用层:常见的应用,文件管理、远程操作等。(HTTP、FTP、SMTP)

表示层:负责定义和转换数据格式。(如选择二进制或ASCII。)

会话层:建立和维持通话。

传输层:定义传输层一些协议。(TCP、UDP协议)


网络层:定义网络节点的逻辑地址。(IP地址)

链路层:通过协议或规程来控制正确性。(MAC)

物理层:提供传输信号和物理介质(网线、光纤等)

五、TCP/IP模型

应用层:即OSI模型中的会话层、表示层、应用层。

传输层

网络层

网络接口层:即OSI模型中的物理层和链路层。

六、TCP\UDP协议

TCP:传输控制协议,面向连接的、可靠的、基于字节流的,数据大小无限制。连接时需要3次握手,断开时需要4次挥手(保证可靠性)。

UDP:用户数据报协议,是一种无连接的传输层协议,简单不可靠的服务。每个包的大小不能超过64KB。

七、IP

是互联网上分配给设备的唯一标识。

分为IPV4和IPV6:

IPV4:是指4个字节,分4段,每段0~255之间,中间使用点号隔开,最大255.255.255.255

IPV6:是指16个字节,分8段,每段0~65535之间,最大FFFF.FFFF.FFFF.FFFF.FFFF.FFFF.FFFF.FFFF

注意:现在是IPV4和IPV6的一个混用的时间节点。

回环地址:127.0.0.1表示本机

查看IP命令:ipconfig

测评IP命令:ping IP地址 -t

八、Port端口

是在设备上对程序的唯一标识。

端口号是一个数字,0~65535区间

系统常用端口010000,意味着写程序时,最好使用10000以后的端口,避免端口冲突。

常用软件的端口:

MySQL:3306

tomcat:8080

Oracle:1521

web服务器默认端口:80

九、InetAddress类

封装IP地址的对象。

  1. public class TestMain {
  2. public static void main(String[] args) throws Exception {
  3. InetAddress addr = InetAddress.getLocalHost(); // 得到本机的信息
  4. System.out.println(addr.getHostName()); // 本机名称
  5. System.out.println(addr.getHostAddress()); // 本机IP
  6. InetAddress addr1 = InetAddress.getByName("LH"); // 通过主机名或者IP地址得到网络上对应设备
  7. System.out.println(addr1.getHostName());
  8. System.out.println(addr1.getHostAddress());
  9. }
  10. }

十、网络编程

10.1 Socket编程

基于TCP协议的编程。

主要分为客户端的Socket(套接字)以及服务器端的ServerSocket

编程时需要知道IP地址和端口号。

编程步骤:

服务器:

  • 创建ServerSocket,指定端口号
  • 调用accept方法,等待客户端接入

客户端:

  • 创建Socket,指定服务器的IP和端口号,建立连接
  • 通过字节流进行输入输出通信

服务端也使用字节流进行输入输出通信。

public class TestServer {
    public static void main(String[] args) throws Exception {
        ServerSocket server = new ServerSocket(6666);
        System.out.println("服务器正在等待客户端的接入");
        Socket socket = server.accept(); // 等待接收客户端接入
        // 读取客户端的内容
        InputStream is = socket.getInputStream();
        byte [] buffer = new byte[1024];
        int len;
        while((len = is.read(buffer)) != -1) {
            String str = new String(buffer, 0, len);
            System.out.println(str);
        }
    }
}
public class TestClient {
    public static void main(String[] args) throws Exception {
        Socket socket = new Socket("192.168.50.70", 6666); // 建立客户端
        System.out.println("客户端建立完成");
        OutputStream os = socket.getOutputStream();
        String str = "hello, world";
        os.write(str.getBytes());
    }
}

10.2 简易聊天室案例
public class MyServer {
    // 定义一个hashmap用来存储所有的客户端
    public static ConcurrentHashMap<String, Socket> map = new ConcurrentHashMap<String, Socket>();
    public static void main(String[] args) {
        try {
            // 创建一个服务器
            ServerSocket server = new ServerSocket(6666);
            System.out.println("服务器创建成功,欢迎您的加入!");
            // 无限循环等待接收客户端的连接
            while(true) {
                Socket socket = server.accept();
                // 得到key(IP地址和端口号)
                String key = socket.getInetAddress().getHostAddress() + ":" + socket.getPort();
                // 将接收到的连接存入集合
                map.put(key, socket);
                // 每接收一个客户端创建一个线程来处理该客户端的消息
                MyServerThread thread = new MyServerThread(socket);
                thread.start();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
public class MyClient {
    public static void main(String[] args) {
        try {
            // 创建一个客户端
            Socket socket = new Socket("192.168.50.70", 6666);
            // 创建一个写的线程来处理该客户端的写操作
            MyClientWriteThread thread = new MyClientWriteThread(socket);
            thread.start();

            // 得到客户端的读取信息的流
            InputStream is = socket.getInputStream();
            // 无限循环读取信息
            while(true) {
                byte [] buffer = new byte[1024];
                int len;
                while((len = is.read(buffer)) != -1) {
                    String str = new String(buffer, 0, len);
                    System.out.println(str);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
public class MyServerThread extends Thread{
    private Socket socket;

    public MyServerThread(Socket socket) {
        super();
        this.socket = socket;
    }

    @Override
    public void run() {
        String key = socket.getInetAddress().getHostAddress() + ":" + socket.getPort();
        System.out.println("欢迎"+key+"加入");
        // 得到客户端信息
        try {
            // 得到客户端输入输出流
            InputStream is = socket.getInputStream();
            OutputStream os = socket.getOutputStream();
            // 无限循环
            while(true) {
                // 接收客户端的信息
                byte [] buffer = new byte[1024];
                int len;
                while((len = is.read(buffer)) != -1) {
                    String msg = new String(buffer, 0, len);
                    System.out.println(msg);
                    // 判断该信息是要群发还是单发
                    String[] arr = msg.split("-");
                    if(arr != null && arr.length == 2) {
                        Socket toSocket = MyServer.map.get(arr[0]);
                        msg = key + "对你说:" + arr[1];
                        // 单独发送消息
                        sendTo(toSocket, msg);
                    }else {
                        // 群发
                        sendToAll(key + "说:" + msg);
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void sendToAll(String msg) {
        for (Socket socket : MyServer.map.values()) {
            sendTo(socket, msg);
        }
    }

    public void sendTo(Socket socket, String msg) {
        try {
            OutputStream os = socket.getOutputStream();
            os.write(msg.getBytes());
            os.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
public class MyClientWriteThread extends Thread{
    private Socket socket;

    public MyClientWriteThread(Socket socket) {
        super();
        this.socket = socket;
    }

    @Override
    public void run() {
        // 得到客户端的输出流
        try {
            OutputStream os = socket.getOutputStream();
            // 定义一个键盘输入
            Scanner input = new Scanner(System.in);
            // 无限循环,接收控制台输入,将其发送(输出)到服务器
            while(true) {
                String str = input.nextLine();
                os.write(str.getBytes());
                os.flush();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}

10.3 udp开发飞秋发消息
public class TestMain1 {
    public static void main(String[] args) {
        sendMsg("一会去看篮球赛");
    }

    private static void sendMsg(String msg) {
        try {
            DatagramSocket ds = new DatagramSocket();
            InetAddress ip = InetAddress.getByName("192.168.50.8"); // ip
            int port = 2425; // 端口号
            // 1:100:飞秋名:主机名:32:信息
            String str = "1:100:程灿:LAPTOP-DL0IQI8H:32:" + msg; // 协议和内容
            // 打包
            DatagramPacket dp = new DatagramPacket(str.getBytes(), str.getBytes().length, ip, port);
            ds.send(dp); // 发送消息
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}