梁恒嘉的技术专栏 全栈之路

Java网络编程


记录计算机网络基础知识,以及Java网络编程,通过ServerSocket创建服务器,使用accept方法阻塞式获取客户端连接。使用Socket创建客户端。使用IO的形式从客户端向服务器发送数据

一、计算机网络定义

计算机网络是通过通信设备和线路将不同地区的计算机连接起来,实现信息与数据共享。

二、网络模型

OSI七层参考模型如下图所示:

OSI七层参考模型

TCP/IP四层协议如下图所示:

TCP/IP四层协议

三、Java网络编程

在Java语言中,可以通过其分装的类库进行网络编程。如:ServerSocket(服务端)与Socket(客户端)。网络编程的核心要素:如何找到网络中的某台主机,如何实现主机之间高效的数据传输。

主机的IP会区别出一台主机,端口会区别出主机中的程序。

高效数据传输通过传输协议去完成。

第一版代码如下:

public class Server {
    public static void main(String[] args) throws IOException {
        ServerSocket socket = new ServerSocket(9966);
        System.out.println("服务器启动成功!等待客户端连接...");
        //监听客户端是否连接服务器。客户端连接后会返回Socket对象。
        //如果一直没有客户端连接,则程序将会阻塞,
        Socket accept = socket.accept();
        System.out.println("客户端连接成功!");

		 //在网络编程中使用的是IO流的形式进行数据传输
        InputStream inputStream = accept.getInputStream();

        byte[] data = new byte[100];
        int size = inputStream.read(data);
        String msg = new String(data,0,size,"UTF-8");
        System.out.println(msg);
    }
}

public class Client {
    public static void main(String[] args) throws IOException {
        //创建客户端,基于TCP的,所以会三次握手,检测主机网络是否畅通
        Socket socket = new Socket("127.0.0.1", 9966);

        //创建输出流,将数据传输到服务器
        OutputStream outputStream = socket.getOutputStream();
        //write()方法里面接受的是byte数组,可以使用getBytes()方法把字符串转化为byte数组
        //getBytes()方法的参数是编码格式
        outputStream.write("你好服务器!".getBytes("UTF-8"));
    }
}

第二版代码如下:

public class TwoServer {
    public static void main(String[] args) throws IOException {
        ServerSocket serverSockets = new ServerSocket(9966);
        Socket socket = serverSockets.accept();
        InputStream in = socket.getInputStream();
        OutputStream out = socket.getOutputStream();
        DataInputStream din = new DataInputStream(in);
        DataOutputStream dout = new DataOutputStream(out);
        Scanner scanner = new Scanner(System.in);
        while (true) {
            String msg = din.readUTF();
            System.out.println("客户端"+socket.getRemoteSocketAddress()+"发来消息:"+msg);

            System.out.println("服务端输入:");
            String serverMsg = scanner.next();
            dout.writeUTF(serverMsg);
        }
    }
}

public class TwoClient {
    public static void main(String[] args) throws IOException {
        Socket socket = new Socket("127.0.0.1",9966);
        InputStream in = socket.getInputStream();
        OutputStream out = socket.getOutputStream();
        DataInputStream din = new DataInputStream(in);
        DataOutputStream dout = new DataOutputStream(out);
        Scanner scanner = new Scanner(System.in);

        while (true){
            System.out.println("客户端输入:");
            String msg = scanner.next();
            dout.writeUTF(msg);

            String serverMsg = din.readUTF();
            System.out.println("服务端发来消息:"+serverMsg);
        }
    }
}

第三版代码如下:

public class UdpServer {
    public static void main(String[] args) throws IOException {
        DatagramSocket datagramSocket = new DatagramSocket(9966);
        byte[] bytes = new byte[1024];
        DatagramPacket datagramPacket = new DatagramPacket(bytes,bytes.length);
        datagramSocket.receive(datagramPacket);
        String clientMsg = new String(bytes,0,datagramPacket.getLength());
        System.out.println(clientMsg);
    }
}


public class UdpClient {
    public static void main(String[] args) throws IOException {

        DatagramSocket socket = new DatagramSocket();
        byte[] bytes = "你好服务端!".getBytes("UTF-8");
        DatagramPacket datagramPacket = new DatagramPacket(bytes,bytes.length, InetAddress.getByName("127.0.0.1"),9966);
        socket.send(datagramPacket);
    }
}

第一版与第二版代码都是使用TCP实现的Socket通信,第三版使用的是UDP实现的Socket通信。

第一版代码实现了客户端与服务端的一次交互。

第二版代码实现了客户端与服务端多次交互,但是由于accept方法与Scanner会阻塞线程,所以交互形式是客户端发起交互,服务端收到交互信息,服务端进行交互,只可以轮流依次交互。

第三版代码使用UDP协议实现了Socket通信,不需要服务端先启动,可以直接发送信息到指定IP地址。

总结

通过ServerSocket创建服务器,使用accept方法阻塞式获取客户端连接。使用Socket创建客户端。使用IO的形式从客户端向服务器发送数据。


Similar Posts

上一篇 Java中的IO流

下一篇 Java中的线程