网络编程

一、什么是网络编程

二、基本的通信架构

三、网络通信的三要素

1.IP地址

1.IPv4,IPv6

2.IP域名

3.公网IP ,内网IP,本机IP

4.InetAddress

java 复制代码
import java.net.InetAddress;


public class InetAddressTest {
    public static void main(String[] args) throws Exception {
        //获取本机IP地址对象
        InetAddress ip1 = InetAddress.getLocalHost ();
        System.out.println ( ip1.getHostAddress () );//获取本机IP地址
        System.out.println ( ip1.getHostName () );//获得主机名

        //2.获取指定IP地址或者域名的对象
        InetAddress ip2 = InetAddress.getByName ( "WWW.baidu.com" );
        System.out.println ( ip2.getHostName () );//WWW.baidu.com
        System.out.println ( ip2.getHostAddress () );//39.156.66.14
        System.out.println ( ip2.isReachable ( 6000 ) );//判断能否联通
    }
}

2.端口号

3.协议

1.什么是协议

2.UDP协议

3.TCP协议

四、网络通信

1.UDP通信

1.常用API
2.代码
java 复制代码
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;

public class Client {
    public static void main(String[] args) throws Exception {
        //1.创建客户端对象(发送方)
        DatagramSocket socket = new DatagramSocket (7777);
        //2.创建数据包对象封装要发出去的数据
//        DatagramPacket(byte[], int length,InetAddress,int port)
/** byte[]:代表要传输的数据
 *  int length:发出去数据的大小
 *  InetAddress:服务端的IP地址
 *  int port:服务端程序的端口号
 *
 */
        byte[] bytes = "我是快乐的客户端,我爱你abc".getBytes ();
        DatagramPacket packet = new DatagramPacket (bytes,bytes.length, InetAddress.getLocalHost (),6666 );
        //3.开始正式发送数据包出去
        socket.send ( packet );
        System.out.println ("客户端数据发送完毕");
        socket.close ();//释放资源


    }
}


import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;

public class Server {
    public static void main(String[] args) throws Exception {
    //1.创建一个服务端对象并注册端口
        DatagramSocket server = new DatagramSocket ( 6666 );
    //2.创建一个数据包对象,用于接受数据
        byte[] bytes = new byte[1024*64];//64kb
        DatagramPacket packet = new DatagramPacket (bytes,bytes.length);
     //3.接收客户端发来的数据
     server.receive ( packet );
     //4.把字节数组中,接受的数据打印出来
        //读取多少倒出多少
        //获取本次数据包接收了多少数据
        int length = packet.getLength ();
        //通过数据包拿到客户端的IP地址
        System.out.println ( packet.getAddress ().getHostAddress () );
        //通过数据包拿到客户端的端口号
        System.out.println ( packet.getPort () );
        String s = new String ( bytes,0,length );
        System.out.println ( s );
        server.close ();
    }
}
3.UDP通信-多发多收
java 复制代码
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.Scanner;

public class Client {
    public static void main(String[] args) throws Exception {
        //1.创建客户端对象(发送方)
        DatagramSocket socket = new DatagramSocket ();
        //2.创建数据包对象封装要发出去的数据
//        DatagramPacket(byte[], int length,InetAddress,int port)
/** byte[]:代表要传输的数据
 *  int length:发出去数据的大小
 *  InetAddress:服务端的IP地址
 *  int port:服务端程序的端口号
 *
 */
        Scanner sc=new Scanner ( System.in );
        while (true) {
            System.out.println ("请说:");
            String msg = sc.nextLine ();
            byte[] bytes1 = msg.getBytes ();
            byte[] bytes = "我是快乐的客户端,我爱你abc".getBytes ();
            DatagramPacket packet = new DatagramPacket (bytes1,bytes1.length, InetAddress.getLocalHost (),6666 );
            //3.开始正式发送数据包出去
            socket.send ( packet );
            if ("exit".equals ( msg )){
                System.out.println ("欢迎下次光临,退出成功");
                break;
            }
        }


    }
}


import java.net.DatagramPacket;
import java.net.DatagramSocket;

public class Server {
    public static void main(String[] args) throws Exception {
    //1.创建一个服务端对象并注册端口
        DatagramSocket server = new DatagramSocket ( 6666 );
    //2.创建一个数据包对象,用于接受数据
        byte[] bytes = new byte[1024*64];//64kb
        DatagramPacket packet = new DatagramPacket (bytes,bytes.length);
     //3.接收客户端发来的数据
        while (true) {
            server.receive ( packet );
            //4.把字节数组中,接受的数据打印出来
            //读取多少倒出多少
            //获取本次数据包接收了多少数据
            int length = packet.getLength ();
            //通过数据包拿到客户端的IP地址
            System.out.println ( packet.getAddress ().getHostAddress () );
            //通过数据包拿到客户端的端口号
            System.out.println ( packet.getPort () );
            String s = new String ( bytes,0,length );
            System.out.println ( s );
            System.out.println ("--------------------------------------------------------------------");
        }

    }
}

2.TCP通信

1.如何实现TCP通信
2.客户端开发
java 复制代码
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;

public class Client {
    public static void main(String[] args) throws Exception {
        //1.创建Socket对象,并同时请求服务器端程序的连接
        Socket socket = new Socket ("127.0.0.1",8888);
        //2.从socket管道中得到一个字节输出流,用来发送数据给服务端
        OutputStream os = socket.getOutputStream ();
        //3.把低级的字节输出流,包装成数据输出流
        DataOutputStream dos = new DataOutputStream ( os );
        //4.开始写数据出去
        dos.writeUTF ( "在一起好吗?" );
        dos.close ();
        socket.close ();
    }
}
3.服务端开发
java 复制代码
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class Server {
    public static void main(String[] args) throws Exception {
        System.out.println ("----------服务端启动成功");
        //1.创建一个服务端对象并设置端口号
        ServerSocket serverSocket = new ServerSocket ( 8888 );
        //2.使用serverSocket对象,调用一个accept方法,等待客户端的连接请求
        Socket socket = serverSocket.accept ();
        //3.从socket通信管道中得到一个字节输入流
        InputStream is = socket.getInputStream ();
        //4.把原始字字节输入流包装成数据输入流
        DataInputStream dis = new DataInputStream ( is );
        //5.使用数据输入流读取客户端发送的消息
        String s = dis.readUTF ();
        System.out.println ( s );
        //获取客户端的IP地址
        System.out.println ( socket.getRemoteSocketAddress () );
        dis.close ();
        socket.close ();


    }
}
4.多发多收
java 复制代码
import java.io.DataOutputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Scanner;

public class Client {
    public static void main(String[] args) throws Exception {
        //1.创建Socket对象,并同时请求服务器端程序的连接
        Socket socket = new Socket ("127.0.0.1",8888);
        //2.从socket管道中得到一个字节输出流,用来发送数据给服务端
        OutputStream os = socket.getOutputStream ();
        //3.把低级的字节输出流,包装成数据输出流
        DataOutputStream dos = new DataOutputStream ( os );
        //4.开始写数据出去
        Scanner scanner = new Scanner (System.in);
        while (true) {
            System.out.println ("请说");
            String s = scanner.nextLine ();
            dos.writeUTF ( s );
            dos.flush ();
            if ("exit".equals ( s )){
                System.out.println ("欢迎下次使用,成功退出");
                dos.close ();
                socket.close ();
            }
        }

    }
}


import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class Server {
    public static void main(String[] args) throws Exception {
        System.out.println ("----------服务端启动成功");
        //1.创建一个服务端对象并设置端口号
        ServerSocket serverSocket = new ServerSocket ( 8888 );
        //2.使用serverSocket对象,调用一个accept方法,等待客户端的连接请求
        Socket socket = serverSocket.accept ();
        //3.从socket通信管道中得到一个字节输入流
        InputStream is = socket.getInputStream ();
        //4.把原始字字节输入流包装成数据输入流
        DataInputStream dis = new DataInputStream ( is );
        //5.使用数据输入流读取客户端发送的消息
        while (true) {
            try {
                String s = dis.readUTF ();
                System.out.println ( s );
                //获取客户端的IP地址
                System.out.println ( socket.getRemoteSocketAddress () );
                System.out.println ("--------------------------------------");
            } catch (IOException e) {
                System.out.println ( socket.getRemoteSocketAddress () + "离线了" );
                socket.close ();
                dis.close ();
                break;
            }
        }



    }
}
5.支持与多个客户端同时通信(上下线逻辑)
java 复制代码
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;

public class ServerReaderThread extends Thread{
    private  Socket socket;
    public ServerReaderThread(){

    }
    public ServerReaderThread(Socket socket){
    this.socket=socket;
    }
    @Override
    public void run() {
        try {
            InputStream is = socket.getInputStream ();
            DataInputStream dis = new DataInputStream ( is );
            while (true) {
                try {
                    String s = dis.readUTF ();
                    System.out.println ( s );
                } catch (Exception e) {

                    System.out.println ("下线了"+socket.getRemoteSocketAddress ());
                    dis.close ();
                    socket.close ();
                    break;
                }
            }
        } catch (Exception e) {
            e.printStackTrace ();
        }
    }
}


import java.io.DataOutputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Scanner;

public class Client {
    public static void main(String[] args) throws Exception {
        //1.创建Socket对象,并同时请求服务器端程序的连接
        Socket socket = new Socket ("127.0.0.1",8888);
        //2.从socket管道中得到一个字节输出流,用来发送数据给服务端
        OutputStream os = socket.getOutputStream ();
        //3.把低级的字节输出流,包装成数据输出流
        DataOutputStream dos = new DataOutputStream ( os );
        //4.开始写数据出去
        Scanner scanner = new Scanner (System.in);
        while (true) {
            System.out.println ("请说");
            String s = scanner.nextLine ();
            dos.writeUTF ( s );
            dos.flush ();
            if ("exit".equals ( s )){
                System.out.println ("欢迎下次使用,成功退出");
                dos.close ();
                socket.close ();
            }
        }

    }
}




import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class Server {
    public static void main(String[] args) throws Exception {
        System.out.println ("----------服务端启动成功");
        //1.创建一个服务端对象并设置端口号
        ServerSocket serverSocket = new ServerSocket ( 8888 );

        while (true) {
            //2.使用serverSocket对象,调用一个accept方法,等待客户端的连接请求
        Socket socket = serverSocket.accept ();
            System.out.println (socket.getRemoteSocketAddress ()+"上线了");
            //3.把这个客户端对应的socket通信管道,交给一个独立的线程负责处理
            new ServerReaderThread (socket).start ();
        }


    }
}

五、TCP 通信综合案例

1.即使通信-群聊

java 复制代码
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;

public class ClientReaderThread extends Thread{
    private Socket socket;
    public ClientReaderThread(){

    }
    public ClientReaderThread(Socket socket){
        this.socket=socket;
    }
    @Override
    public void run() {
        try {
            InputStream is = socket.getInputStream ();
            DataInputStream dis = new DataInputStream ( is );
            while (true) {
                try {
                    String s = dis.readUTF ();
                    System.out.println ( s );
                    //把这个消息发给全部的客户端进行接受
                    sendMsgAll(s);
                } catch (Exception e) {

                    System.out.println ("自己下线了"+socket.getRemoteSocketAddress ());

                    dis.close ();
                    socket.close ();
                    break;
                }
            }
        } catch (Exception e) {
            e.printStackTrace ();
        }

    }
    private void sendMsgAll(String s) throws Exception {
        //发送给全部在线的Socket对象
        for (Socket onLineSocket : Server.onLineSockets) {
            OutputStream os = onLineSocket.getOutputStream ();
            DataOutputStream dos = new DataOutputStream ( os );
            dos.writeUTF ( s );
            dos.flush ();
        }}
}

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

public class ServerReaderThread extends Thread{
    private  Socket socket;
    public ServerReaderThread(){

    }
    public ServerReaderThread(Socket socket){
    this.socket=socket;
    }
    @Override
    public void run() {
        try {
            InputStream is = socket.getInputStream ();
            DataInputStream dis = new DataInputStream ( is );
            while (true) {
                try {
                    String s = dis.readUTF ();
                    System.out.println ( s );
                    //把这个消息发给全部的客户端进行接受
                    sendMsgAll(s);
                } catch (Exception e) {

                    System.out.println ("下线了"+socket.getRemoteSocketAddress ());
                    Server.onLineSockets.remove ( socket );//离线时抹掉Socket
                    dis.close ();
                    socket.close ();
                    break;
                }
            }
        } catch (Exception e) {
            e.printStackTrace ();
        }
    }

    private void sendMsgAll(String s) throws Exception {
        //发送给全部在线的Socket对象
        for (Socket onLineSocket : Server.onLineSockets) {
            OutputStream os = onLineSocket.getOutputStream ();
            DataOutputStream dos = new DataOutputStream ( os );
            dos.writeUTF ( s );
            dos.flush ();
        }
    }
}

import java.io.DataOutputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Scanner;

public class Client {
    public static void main(String[] args) throws Exception {
        //1.创建Socket对象,并同时请求服务器端程序的连接
        Socket socket = new Socket ("127.0.0.1",8888);
        //创建一个独立的线程,负责随时从socket中接受来自服务端的消息
        new ClientReaderThread (socket).start ();

        //2.从socket管道中得到一个字节输出流,用来发送数据给服务端
        OutputStream os = socket.getOutputStream ();
        //3.把低级的字节输出流,包装成数据输出流
        DataOutputStream dos = new DataOutputStream ( os );
        //4.开始写数据出去
        Scanner scanner = new Scanner (System.in);
        while (true) {
            System.out.println ("请说");
            String s = scanner.nextLine ();
            dos.writeUTF ( s );
            dos.flush ();
            if ("exit".equals ( s )){
                System.out.println ("欢迎下次使用,成功退出");
                dos.close ();
                socket.close ();
            }
        }

    }
}



import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;

public class Server {
    public static List<Socket> onLineSockets=new ArrayList<> ();
    public static void main(String[] args) throws Exception {
        System.out.println ("----------服务端启动成功");
        //1.创建一个服务端对象并设置端口号
        ServerSocket serverSocket = new ServerSocket ( 8888 );

        while (true) {
            //2.使用serverSocket对象,调用一个accept方法,等待客户端的连接请求
        Socket socket = serverSocket.accept ();
        onLineSockets.add ( socket );//有连接就存储Socket管道
            System.out.println (socket.getRemoteSocketAddress ()+"上线了");
            //3.把这个客户端对应的socket通信管道,交给一个独立的线程负责处理
            new ServerReaderThread (socket).start ();
        }


    }
}

2.实现一个简易的BS架构

B/S架构
java 复制代码
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;

public class Server {
    public static List<Socket> onLineSockets=new ArrayList<> ();
    public static void main(String[] args) throws Exception {
        System.out.println ("----------服务端启动成功");
        //1.创建一个服务端对象并设置端口号
        ServerSocket serverSocket = new ServerSocket ( 8888 );

        while (true) {
            //2.使用serverSocket对象,调用一个accept方法,等待客户端的连接请求
        Socket socket = serverSocket.accept ();
        onLineSockets.add ( socket );//有连接就存储Socket管道
            System.out.println (socket.getRemoteSocketAddress ()+"上线了");
            //3.把这个客户端对应的socket通信管道,交给一个独立的线程负责处理
            new ServerReaderThread (socket).start ();
        }


    }
}



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

public class ServerReaderThread extends Thread{
    private  Socket socket;
    public ServerReaderThread(){

    }
    public ServerReaderThread(Socket socket){
    this.socket=socket;
    }
    @Override
    public void run() {
       //立即响应一个网页内容:"黑马程序员"给浏览器提示
        try {
            OutputStream os = socket.getOutputStream ();
            PrintStream ps = new PrintStream ( os );
            ps.println ("HTTP/1.1 200 OK");
            ps.println ("Content-Type:text/html;charset=UTF-8");
            ps.println ();//必须换行
            ps.println ("<div >黑马666</div>");
            socket.close ();//响应网页短连接

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


}
使用线程池优化
java 复制代码
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class Server {
    public static List<Socket> onLineSockets=new ArrayList<> ();
    public static void main(String[] args) throws Exception {
        System.out.println ("----------服务端启动成功");
        //1.创建一个服务端对象并设置端口号
        ServerSocket serverSocket = new ServerSocket ( 8888 );
        //创建一个线程池,负责处理通信管道的任务
        ThreadPoolExecutor pool = new ThreadPoolExecutor (16*2,16*2,0, TimeUnit.SECONDS,
        new ArrayBlockingQueue<> ( 8 ), Executors.defaultThreadFactory (),new ThreadPoolExecutor.AbortPolicy () );

        while (true) {
            //2.使用serverSocket对象,调用一个accept方法,等待客户端的连接请求
        Socket socket = serverSocket.accept ();
        onLineSockets.add ( socket );//有连接就存储Socket管道
            System.out.println (socket.getRemoteSocketAddress ()+"上线了");
            //3.把这个客户端对应的socket通信管道,交给一个独立的线程负责处理
            //把通信管道封装成任务对象
            pool.execute ( new ServerReaderRunnable (socket));

        }


    }
}



import java.io.OutputStream;
import java.io.PrintStream;
import java.net.Socket;

public class ServerReaderRunnable implements Runnable{
    private  Socket socket;
    public ServerReaderRunnable(){

    }
    public ServerReaderRunnable(Socket socket){
    this.socket=socket;
    }
    @Override
    public void run() {
       //立即响应一个网页内容:"黑马程序员"给浏览器提示
        try {
            OutputStream os = socket.getOutputStream ();
            PrintStream ps = new PrintStream ( os );
            ps.println ("HTTP/1.1 200 OK");
            ps.println ("Content-Type:text/html;charset=UTF-8");
            ps.println ();//必须换行
            ps.println ("<div >黑马666</div>");
            socket.close ();//响应网页短连接

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


}
相关推荐
大树883 天前
金刚石散热越强,管路越先见顶
大数据·运维·服务器·人工智能·ai
摇滚侠3 天前
Linux CentOS7 rpm 安装 MySQL 5.7
linux·运维·mysql
霸道流氓气质3 天前
领域驱动设计(DDD)在 Spring Boot 微服务中的实践指南
运维·spring boot·微服务
小宇宙Zz3 天前
Maven依赖冲突
java·服务器·maven
Inhand陈工3 天前
基于台达PLC与映翰通IG502的智慧水产养殖精准投喂与远程运维解决方案
运维·人工智能·物联网·阿里云·信息与通信
网络研究院3 天前
2026年网络安全
网络·安全·法律·法规·趋势·发展
酣大智3 天前
ARP代理--工作原理
运维·网络·arp·arp代理
treesforest3 天前
AI安全系统如何识别异常访问?IP风险识别正在成为关键能力
网络·人工智能·tcp/ip·安全·web安全
shushangyun_3 天前
2026年快消品B2B系统推荐:支持终端门店订货、促销政策自动化的工具?
java·运维·网络·数据库·人工智能·spring·自动化
古城小栈3 天前
Unix 与 Linux 异同小叙
linux·服务器·unix