JAVA网络编程TCP通信

时间:2022-07-24
本文章向大家介绍JAVA网络编程TCP通信,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

Socket简介:

Socket称为“套接字”,描述IP地址和端口。在Internet上的主机一般运行多个服务软件,同时提供几种服务,每种服务都打开一个Socket,并绑定在一个端口上,不同的端口对应于不同的服务。Socket和ServerSocket类位于java.net包中。ServerSocket用于服务端,Socket是建立网络连接时使用的。连接成功时,应用程序两端都会产生一个Socket实例,通过操作这个实例完成所需会话。

Socket常用方法:

-int getLocalPort() 获取本地使用的端口号

-InetAddress getLocalAddress() 获取套接字绑定的本地地址

-int getPort() 获取远端使用的端口号

-InetAddress.getInetAddress() 获取套接字绑定的远端地址

InetAddress常用方法:

-String getCanonicalHostName() 获取此IP地址的完全限定域名。

-String getHostAddress() 返回IP地址字符串

1 //获取本地地址和端口号:
2   public void testSocket() throws Exception{
3       Socket socket=new Socket("localhost",8088);
4       InetAddress add=socket.getLocalAddress();
5       System.out.println(add.getCanonicalHostName());
6       System.out.println(add.getHostName());
7       System.out.println(add.getLocalPort());
8   }
1 //获取远端地址和端口号:
2     public static void testSocket() throws Exception{
3         Socket socket=new Socket("localhost",8088);
4         InetAddress inetAdd=socket.getInetAddress();
5         System.out.println(inetAdd.getCanonicalHostName());
6         System.out.println(inetAdd.getHostName());
7         System.out.println(socket.getLocalPort());
8     }

其他方法的使用:

package com.demo.inet;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Arrays;

public class InetAddressDemo {
    public static void main(String[] args) {
        // 创建一个字节数组byte 127 ~ -128
        byte bt[] = {-64,-88,3,44};//192.168.3.44
        
        try {
            // 创建InetAddress对象
            InetAddress id = InetAddress.getByAddress(bt);
            System.out.println(id);
            // 返回原始IP地址
            byte[] bs = id.getAddress();
            System.out.println(Arrays.toString(bs));
            // 返回对象对应IP地址
            System.out.println(id.getHostAddress());
            // 返回全名计算名称
            System.out.println(id.getCanonicalHostName()+"------------------");
            
            // 返回本机计算机名及对应ip地址
            System.out.println(InetAddress.getLocalHost());
            
            // 返回host名称对应域名及ip地址
            InetAddress[] allByName = InetAddress.getAllByName("www.baidu.com");
            System.out.println(Arrays.toString(allByName));
            System.out.println(allByName[0].getHostName()); // 域名
            System.out.println(allByName[0].getHostAddress()); // ip地址
            
            // 同主机名称获取IP信息
            InetAddress addr = InetAddress.getByName("localhost");
            System.out.println(addr.getHostAddress());
            System.out.println(addr.getCanonicalHostName()); // 返回ip地址
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }
    }
}

获取网络输入流和网络输出流

通过Socket获取输入流与输出流,主要使用一下两个方法

-InputStream getInputStream() 用于返回此套接字的输入流

-OutStream getOutputStream() 用于返回此套接字的输出流

public static void testSocket() throws Exception {
        Socket socket = new Socket("localhost", 8088);
        OutputStream out = socket.getOutputStream();
        OutputStreamWriter osw = new OutputStreamWriter(out, "UTF-8");
        PrintWriter pw = new PrintWriter(osw, true);
        pw.println("输出的内容");//发送内容
        InputStream in=socket.getInputStream();
        InputStreamReader isr=new InputStreamReader(in, "UTF-8");
        BufferedReader br=new BufferedReader(isr);
        br.readLine();//读取接到的内容
 }

注意:当使用完Socket进行通讯完毕后,要关闭Socket以释放系统资源

-void close() 关闭套接字,同时也代表关闭了获取的输入与输出流。

服务端ServerSocket监听

1 //创建ServerSocket并申请服务端口8088
2 ServerSocket server=new ServerSocket(8088);
3 /*方法会产生阻塞,直到某个Socket连接,并返回请求连接的Socket*/
4 Socket socket=server.accept();
5 ...

客户端Socket连接

1 //参数1:服务端的IP地址,参数2:服务端的服务器端口
2 //注意:创建Socket的同时就会发起连接,若连接失败会抛出异常
3 Socket socket=new Socket("localhost",8088);
4 ....

C-S端通信模型

详细实例演示

Server:

package com.demo.server;

import java.io.BufferedOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

public class Server {

    static int port = 12345;

    public static void main(String[] args) {
        // 创建服务端Socket对象
        ServerSocket serverSocket = null;
        while (true) {
            try {
                // 创建服务端Socket对象
                serverSocket = new ServerSocket(port);
                System.out.println("等待客户端连接服务器.......");
                // 阻塞服务器
                Socket socket = serverSocket.accept();
                System.out.println("客户端连接到服务器.......");

                // 创建文件输出流
                BufferedOutputStream os = new BufferedOutputStream(socket.getOutputStream());
                os.write("服务器端: 我收到了客户端连接请求。".getBytes());
                os.flush();
                os.close();

            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                try {
                    if (serverSocket != null) {
                        serverSocket.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

}

Client:

package com.demo.client;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.net.Socket;

public class Client {
    static int port = 12345;
    static String host = "111.231.93.134";

    public static void main(String[] args) {
        // 创建客户端对象
        Socket socket = null;
        try {
            // 创建客户端对象
            socket = new Socket(host, port);
            
            // 获取输入流对象
            BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
            // 定义缓冲字节数组
            byte[] buffer = new byte[1024];
            // 定义接收实际长度
            int len = 0;
            while ((len = bis.read(buffer)) != -1) {
                String content = new String(buffer, 0, len);
                System.out.println("客户端接收的内容:"+content);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (socket != null) {
                    socket.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

TCP与UDP的区别

TCP(Transmission Control Protocol,传输控制协议)是基于连接的协议,也就是说,在正式收发数据前,必须和对方建立可靠的连接。聊天工具使用TCP协议

UDP(User Data Protocol,用户数据报协议)是与TCP相对应的协议。它是面向非连接的协议,它不与对方建立连接,而是直接就把数据包发送过去! 游戏多使用UDP协议

UDP程序演示:

Server:

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
 
/*
 * 服务器端,实现基于UDP的用户登陆
 */
public class UDPServer {
    public static void main(String[] args) throws IOException {
        /*
         * 接收客户端发送的数据
         */
        // 1.创建服务器端DatagramSocket,指定端口
        DatagramSocket socket = new DatagramSocket(8800);
        // 2.创建数据报,用于接收客户端发送的数据
        byte[] data = new byte[1024];// 创建字节数组,指定接收的数据包的大小
        DatagramPacket packet = new DatagramPacket(data, data.length);
        // 3.接收客户端发送的数据
        System.out.println("****服务器端已经启动,等待客户端发送数据");
        socket.receive(packet);// 此方法在接收到数据报之前会一直阻塞
        // 4.读取数据
        String info = new String(data, 0, packet.getLength());
        System.out.println("我是服务器,客户端说:" + info);
 
        /*
         * 向客户端响应数据
         */
        // 1.定义客户端的地址、端口号、数据
        InetAddress address = packet.getAddress();
        int port = packet.getPort();
        byte[] data2 = "欢迎您!".getBytes();
        // 2.创建数据报,包含响应的数据信息
        DatagramPacket packet2 = new DatagramPacket(data2, data2.length, address, port);
        // 3.响应客户端
        socket.send(packet2);
        // 4.关闭资源
        socket.close();
    }
}

Client:

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
 
/*
 * 客户端
 */
public class UDPClient {
    public static void main(String[] args) throws IOException {
        /*
         * 向服务器端发送数据
         */
        // 1.定义服务器的地址、端口号、数据
        InetAddress address = InetAddress.getByName("localhost");
        int port = 8800;
        byte[] data = "用户名:admin;密码:123".getBytes();
        // 2.创建数据报,包含发送的数据信息
        DatagramPacket packet = new DatagramPacket(data, data.length, address, port);
        // 3.创建DatagramSocket对象
        DatagramSocket socket = new DatagramSocket();
        // 4.向服务器端发送数据报
        socket.send(packet);
 
        /*
         * 接收服务器端响应的数据
         */
        // 1.创建数据报,用于接收服务器端响应的数据
        byte[] data2 = new byte[1024];
        DatagramPacket packet2 = new DatagramPacket(data2, data2.length);
        // 2.接收服务器响应的数据
        socket.receive(packet2);
        // 3.读取数据
        String reply = new String(data2, 0, packet2.getLength());
        System.out.println("我是客户端,服务器说:" + reply);
        // 4.关闭资源
        socket.close();
    }
}