JAVA网络编程

1.网络

1.1计算机网络

计算机网络:分布在不同地理位置上的计算机,通过专用的线路和设备连在一起,可以共享硬件、软件、数据。

1.2网络编程

网络编程:就是使用计算机语言编写可以在互联网上相互通信的软件。

 

1.3 IP地址

IP规定了计算机在网络中的地址,一台计算机只有符合IP才可以连接到互联网上,和其他计算机相互通信。IP地址是互联网中其他电脑找到你这台电脑的唯一依据。

2.传输协议

2.1 TCP

TCP:传输控制协议,面向连接,安全、可靠。缺点:速度慢。例如:打电话

 

2.2 UDP(用户数据报协议)

发电报、发短信(面向无连接,不安全,不可靠),有点:速度快。

 

3.JAVA网络编程

java网络编程采用的是套接字(Socket)编程模型。无论是 TCP 还是 UDP 协议都采用统一的套接字编程。

TCP程序要先启动服务器程序,然后才是客户端程序。

 

UDP必须先启动客户端,然后才是服务器。

 

4.Code Demo

4.1 服务端与客户端建立通信连接

(1)客户端

点击查看代码
import java.io.DataOutputStream;
import java.io.OutputStream;
import java.net.Socket;

public class ClientSocket {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        try {
            //创建客户端套接字,用于交互服务端     指定服务器ip + 端口号
            Socket socket = new Socket("127.0.0.1", 9999);
            //根据套接字获取输出流
            OutputStream outputStream = socket.getOutputStream();
            
            //将字节输出流包装成  数据字节输出流|特殊流
            DataOutputStream dataOutputStream = new DataOutputStream(outputStream);
            dataOutputStream.writeUTF("hello 服务器!");

            dataOutputStream.flush();
        } catch (Exception e) {
            // TODO: handle exception
            e.printStackTrace();
        }
    }

}

(2)服务端

点击查看代码
import java.io.DataInputStream;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class ServerSocket {

    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub

        try {
            //创建ServerSocket(服务端套接字)   并指定端口号,不需要指定ip
            ServerSocket serverSocket = new ServerSocket(9999);
            System.out.println("---------服务端暴露成功----9999---");

            //通过服务端套接字  监听客户端的连接,如果没有客户端连接,那么程序会一直停留在此处,accept方法的返回值就是 客户端的套接字,通过该套接字可以与客户端交互
            Socket socket = serverSocket.accept();
            //根据客户端套接字,获取对应的输入流,通过此输入流就能拿到客户端发送过来的信息
            InputStream inputStream = socket.getInputStream();

            //将输入字节流包装成特殊数据处理流
            DataInputStream dataInputStream = new DataInputStream(inputStream);
            System.out.println(dataInputStream.readUTF());
            System.out.println("--------程序执行完毕---------");

        } catch (Exception e) {
            // TODO: handle exception
            e.printStackTrace();
        }
    }

}

4.2 服务端与客户端连续通信(来回发送)

(1)客户端

点击查看代码
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.net.Socket;
import java.util.Scanner;

/**
 * Version:1.0
 * 1、客户端不断发送信息给服务端,并且获取服务端发送的信息
 * 2、一个客户端,一个服务端
 */
public class ClientSocket {
	//定义Scanner用户获取输入的信息
	private static Scanner scanner = new Scanner(System.in);

	public static void main(String[] args) {
		try {
			//创建客户端套接字
			Socket socket = new Socket("127.0.0.1", 9999);
			while (true) {
				DataOutputStream dataOutputStream = new DataOutputStream(socket.getOutputStream());
				DataInputStream dataInputStream = new DataInputStream(socket.getInputStream());
				//创建数据字节输出流
				dataOutputStream.writeUTF("客户端:" + scanner.next());

				//获取服务端发送的信息
				String message = dataInputStream.readUTF();
				System.out.println(message);
			}

		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}
	}
}

(2)服务端

点击查看代码
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;

/**
 * Version:1.0
 * 1、服务端可以不断获取客户端发送的信息,并且发送信息给客户端
 * 2、一个客户端,一个服务端
 */
public class ServerSocket{

	//定义Scanner用户获取输入的信息
	private static Scanner scanner = new Scanner(System.in);

	public static void main(String[] args) {
		try {

			//创建服务端套接字
			ServerSocket serverSocket = new ServerSocket(9999);
			//获取客户端套接字|请求
			Socket socket = serverSocket.accept();
			while (true) {
				DataInputStream dataInputStream = new DataInputStream(socket.getInputStream());
				//获取客户端发送的信息
				String message = dataInputStream.readUTF();
				System.out.println(message);

				//服务端继续给客户端发送信息
				DataOutputStream dataOutputStream = new DataOutputStream(socket.getOutputStream());
				dataOutputStream.writeUTF("服务端:" + scanner.next());
				dataOutputStream.flush();
			}
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}
	}
}

注:以上通信只能实现客户端与服务端轮流发送消息,客户端发送消息之后需要等待服务端响应之后才能继续发送消息,否则客户端一直处于阻塞状态,无法实现客户端与服务端独立发送消息和接收消息。要想实现客户端与服务端独立收发消息,则需要实现收、发分离。

4.3 客户端与服务端独立收、发消息

(1)客户端

点击查看代码
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.net.Socket;
import java.util.Scanner;

/**
 * Version:1.0
 * 1、客户端不断发送信息给服务端,并且获取服务端发送的信息
 * 2、一个客户端,一个服务端
 */
public class ClientSocket {

    //定义Scanner用户获取输入的信息
    private static Scanner scanner = new Scanner(System.in);

    public static void main(String[] args) {
        try {
            //创建客户端套接字
            Socket socket = new Socket("127.0.0.1", 9999);

            //开启线程用于读取服务器发送的信息
            new ThreadClient(socket).start();
            while (true) {
                //发送信息至服务器
                DataOutputStream dataOutputStream = new DataOutputStream(socket.getOutputStream());
                //创建数据字节输出流
                dataOutputStream.writeUTF("客户端:" + scanner.next());
            }
        } catch (Exception e) {
            // TODO: handle exception
            e.printStackTrace();
        }
    }
}

class ThreadClient extends Thread {

    private Socket socket;

    public ThreadClient() {

    }

    public ThreadClient(Socket socket) {
        this.socket = socket;
    }

    //重写Thread类的run方法,在该方法中负责读取服务器发送的信息
    @Override
    public void run() {
        try {
            while (true) {
                DataInputStream dataInputStream = new DataInputStream(socket.getInputStream());
                //获取服务端发送的信息
                String message = dataInputStream.readUTF();
                System.out.println(message);
            }

        } catch (Exception e) {
            // TODO: handle exception
            e.printStackTrace();
        }
    }
}

(2)服务端

点击查看代码
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;

/**
 * Version:1.0
 * 1、服务端可以不断获取客户端发送的信息,并且发送信息给客户端
 * 2、一个客户端,一个服务端
 */
public class ServerSocketTest {

    public static void main(String[] args) {
        try {
            //创建服务端套接字
            ServerSocket serverSocket = new ServerSocket(9999);
            //获取客户端套接字|请求
            Socket socket = serverSocket.accept();
            //开启线程用户发送信息给客户端
            new ThreadServer(socket).start();
            while (true) {
                DataInputStream dataInputStream = new DataInputStream(socket.getInputStream());
                //获取客户端发送的信息
                String message = dataInputStream.readUTF();
                System.out.println(message);
            }
        } catch (Exception e) {
            // TODO: handle exception
            e.printStackTrace();
        }
    }
}


class ThreadServer extends Thread {
    //定义Scanner用户获取输入的信息
    private static Scanner scanner = new Scanner(System.in);

    private Socket socket;

    public ThreadServer() {

    }

    public ThreadServer(Socket socket) {
        this.socket = socket;
    }
    
    //重写Thread类的run方法,在该方法中负责读取服务器发送的信息
    @Override
    public void run() {
        try {
            while (true) {
                //服务端继续给客户端发送信息
                DataOutputStream dataOutputStream = new DataOutputStream(socket.getOutputStream());
                dataOutputStream.writeUTF("服务端:" + scanner.next());
                dataOutputStream.flush();
            }

        } catch (Exception e) {
            // TODO: handle exception
            e.printStackTrace();
        }
    }
}

4.4 多个客户端、一个服务端

(1)客户端1

点击查看代码
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.net.Socket;
import java.util.Scanner;

/**
 * Version:1.0
 * 1、客户端不断发送信息给服务端,并且获取服务端发送的信息
 * 2、多个客户端,一个服务端
 */
public class SocketTest {

    //定义Scanner用户获取输入的信息
    private static Scanner scanner = new Scanner(System.in);

    public static void main(String[] args) {
        try {
            //创建客户端套接字
            Socket socket = new Socket("10.74.69.10", 9999);
            //开启线程用于读取服务器发送的信息
            new ThreadClient(socket).start();
            while (true) {
                //发送信息至服务器
                DataOutputStream dataOutputStream = new DataOutputStream(socket.getOutputStream());
                //创建数据字节输出流
                dataOutputStream.writeUTF("客户端A:" + scanner.next());

            }
            
        } catch (Exception e) {
            // TODO: handle exception
            e.printStackTrace();
        }
    }
}

class ThreadClient extends Thread {

    private Socket socket;

    public ThreadClient() {

    }

    public ThreadClient(Socket socket) {
        this.socket = socket;
    }
    
    //重写Thread类的run方法,在该方法中负责读取服务器发送的信息
    @Override
    public void run() {

        try {

            while (true) {
                DataInputStream dataInputStream = new DataInputStream(socket.getInputStream());
                //获取服务端发送的信息
                String message = dataInputStream.readUTF();
                System.out.println(message);

            }

        } catch (Exception e) {
            // TODO: handle exception
            e.printStackTrace();
        }
    }
}

(2)客户端2

点击查看代码

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

/**
 * Version:1.0
 * 1、客户端不断发送信息给服务端,并且获取服务端发送的信息
 * 2、多个客户端,一个服务端
 */
public class SocketTest2 {
    //定义Scanner用户获取输入的信息
    private static Scanner scanner = new Scanner(System.in);

    public static void main(String[] args) {
        try {
            //创建客户端套接字
            Socket socket = new Socket("10.74.69.10", 9999);
            //开启线程用于读取服务器发送的信息
            new ThreadClient2(socket).start();
            while (true) {
                //发送信息至服务器
                DataOutputStream dataOutputStream = new DataOutputStream(socket.getOutputStream());
                //创建数据字节输出流
                dataOutputStream.writeUTF("客户端B:" + scanner.next());
            }
        } catch (Exception e) {
            // TODO: handle exception
            e.printStackTrace();
        }
    }
}

class ThreadClient2 extends Thread {

    private Socket socket;

    public ThreadClient2() {
    }

    public ThreadClient2(Socket socket) {
        this.socket = socket;
    }

    //重写Thread类的run方法,在该方法中负责读取服务器发送的信息
    @Override
    public void run() {
        try {
            while (true) {
                DataInputStream dataInputStream = new DataInputStream(socket.getInputStream());
                //获取服务端发送的信息
                String message = dataInputStream.readUTF();
                System.out.println(message);
            }

        } catch (Exception e) {
            // TODO: handle exception
            e.printStackTrace();
        }
    }
}

(3)服务端

点击查看代码

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;

/**
 * Version:1.0
 * 1、服务端可以不断获取客户端发送的信息,并且发送信息给客户端
 * 2、多个客户端,一个服务端
 */
public class ServerSocketTest {
	//定义集合用于存储所有的客户端Socket套接字
	public final static List<Socket> socketList = new ArrayList<>();

	public static void main(String[] args) {
		try {
			//创建服务端套接字
			ServerSocket serverSocket = new ServerSocket(9999);
			System.out.println("-----------服务端暴露成功-------");
			while (true) {
				//获取客户端套接字|请求,因为我们的服务端可以监听N个客户端,因此  将  serverSocket.accept()  放在循环中
				Socket socket = serverSocket.accept();
				System.out.println("socket:" + socket);
				//将客户端 Socket存放在 集合中
				socketList.add(socket);
				System.out.println("当前在线人数:" + socketList.size());
				//开启线程用户发送信息给客户端
				new ThreadServer(socket).start();
			}
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}
	}
}

class ThreadServer extends Thread {
	private Socket socket;

	public ThreadServer() {
	}

	public ThreadServer(Socket socket) {
		this.socket = socket;
	}

	//重写Thread类的run方法,在该方法中负责读取服务器发送的信息
	@Override
	public void run() {
		try {
			while (true) {
				//获取客户端发送的信息
				DataInputStream dataInputStream = new DataInputStream(socket.getInputStream());
				String message = dataInputStream.readUTF();
				//将信息广播给每一个客户端
				for (int i = 0; i < ServerSocketTest.socketList.size(); i++) {
					Socket socket = ServerSocketTest.socketList.get(i);
					DataOutputStream dataOutputStream = new DataOutputStream(socket.getOutputStream());
					dataOutputStream.writeUTF(message);
					//刷新
					dataOutputStream.flush();
				}
			}
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}
	}
}

 

posted @ 2021-12-06 22:39  BlogMemory  阅读(33)  评论(0编辑  收藏  举报