Socket通信模型

socket:两个Java应用程序可通过一个双向的网络通信连接实现数据交互,这个双向链路的一端称为一个socket

1.socket通信模型之TCP协议:

java.net包中定义的两个类Socket和ServerSocket,分别用来是实现双向链接的client端和server端

代码实现:

客户端:

public static void main(String[] args) {
        try {
            Socket socket = new Socket("127.0.0.1", 6666);//创建socket客户端,并设置监听地址及端口
            //向服务端发出消息
            OutputStream outputStream = socket.getOutputStream();//因为客户端是要向服务端发出消息,即写出,因此使用OutputStream()来向socket服务端发送消息
            DataOutputStream dos = new DataOutputStream(outputStream);//为了方便我们直接写入字符或数字类型,使用数据流DataOutputStream()对输出流OutputStream()进行封装
            dos.writeUTF("Hello Server!");//向输出流中写入UTF编码的字符串
            //接收服务端的消息
            InputStream inputStream = socket.getInputStream();  //接收服务端发出的消息对于客户端来说为写入,因此使用InputStream()来接收socket服务端发送的消息
            InputStreamReader isr = new InputStreamReader(inputStream);//转换为字符流
            BufferedReader br = new BufferedReader(isr);//转换为缓冲流,从而使用缓冲流的readLine()方法直接读取一行
            System.out.println(br.readLine());

            dos.flush();//将输出流管道中的数据做一次推送,保证完全发出去
            dos.close();//关闭输出流
            isr.close();//关闭输入流
            socket.close();//关闭socket
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

服务端:

public static void main(String[] args) {
        try {
            ServerSocket serverSocket = new ServerSocket(6666);//创建socket服务端,并设置端口号
            Socket socket = serverSocket.accept();//accept()为接受来自客户端的请求连接信息,此方法为阻塞式方法,即没有客户端连接的情况下,会一直阻塞在此处,不会往下执行
            System.out.println("连接成功");
            //接收客户端的消息
            InputStream inputStream = socket.getInputStream();//接收客户端消息,即为写入,因此使用InputStream()来接收Socket客户端发来的消息
            DataInputStream dis = new DataInputStream(inputStream);//为了方便我们直接读取字符或数字类型,使用数据流DataInputStream()对输入流InputStream()进行封装
            String result = dis.readUTF();
            System.out.println("收到来自:"+socket.getInetAddress()+":"+socket.getPort()+"的消息:"+result);
            //向客户端发出消息
            OutputStream outputStream = socket.getOutputStream();//向Socket客户端发出消息
            OutputStreamWriter osw = new OutputStreamWriter(outputStream);
            osw.write("Hello Client!");

            osw.flush();
            osw.close();
            dis.close();
            socket.close();

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

    }

注意:启动时,需要先启动服务端,后启动客户端

2.Socket通信模型之UDP协议:

UDP协议下来说,是没有客户端和服务端之说的,分为消息的发送方和接收方。

代码实现:

发送方:

public static void main(String[] args) {
long message = 10000L;    //定义要传送的“消息”
        try {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();//在内存中创建一块字节数组区域,用以存放字节数组,并将其转换为字节数组,ByteArrayOutputStream()主要作用为将数据转为字节数组
            DataOutputStream dos = new DataOutputStream(baos);//使用数据流DataOutputStream来写入double/int/float/long等数字类型到字节数组
            dos.writeLong(message);   //将数据写入到字节数组中,以便于转换为字节数组
            dos.flush();
            dos.close();

            byte buf[] = baos.toByteArray();//将刚刚在内存中创建并存放数据的字节数组中的字节数组获取出来
            DatagramPacket dp = new DatagramPacket(buf,0,buf.length,new InetSocketAddress("127.0.0.1",6789));//UDP协议发出或接收数据需要使用数据包来对数据做一个包裹,因此创建数据包用于包裹字节数组,需注明使用的数组、数组中数据长度
            DatagramSocket ds = new DatagramSocket(9876);//创建UDP协议的Socket对象用以传输数据,并设置自己端口号
            ds.send(dp);//send()发送消息
            ds.close();
        }catch (IOException e)
        {
            e.printStackTrace();
        }
}

接收方:

public static void main(String[] args) {
    try {
            byte buf[] = new byte[1024];//定义长度为1024的字节数组,用于存放字节信息
            DatagramSocket ds = new DatagramSocket(6789);//创建UDP协议的Socket对象用以传输数据,并设置自己端口号
            DatagramPacket dp = new DatagramPacket(buf,0,buf.length);//UDP协议发出或接收数据需要使用数据包来对数据做一个包裹,因此创建数据包用于包裹字节数组,需注明使用的数组、数组中数据长度
            ds.receive(dp);//receive()用以接收发送端发出的消息
            //以上操作为,定义数据载体字节数组以及一个DatagramPacket()来包裹字节数组,DatagramSocket()使用DatagramPacket()来接收数据,最终数据会被存放在buf[]中
            //下边对buf[]中的数据进行读取
            ByteArrayInputStream bais = new ByteArrayInputStream(buf);//在内存中创建一块字节数组区域,用以存放字节数组
            DataInputStream dis = new DataInputStream(bais);//使用数据流DataInputStream来读取double/int/float/long等数字类型到字节数组
            long message = dis.readLong();  //读取
            System.out.println("接收到的消息为:"+message);

            dis.close();
            ds.close();
        }catch (IOException e)
        {
            e.printStackTrace();
        }    
}

注:

1.UDP在传输信息时需将消息转为字节数组放到数据包DatagramPacket(),上边使用的ByteArrayInputStream()和ByteArrayOutputStream()是在内存中开辟一块区域用于存放字节数组,目的是为了将数字类型的消息转为字节数组,使用其提供的toByteArray()即可实现:

Socket通信模型_第1张图片

2.但是如果我们传输的是字符类型的话,可直接使用String提供的getBytes()来得到对应的字节数组:

Socket通信模型_第2张图片

Socket通信模型_第3张图片

你可能感兴趣的:(Java基础)