Java网编之:Socket套接字

目录

一、Socket概念

二、Socket基本操作

三、Socket建立通信原理

四、服务器端:ServerSocket类

1、构造方法

2、常用方法

五、客户端与服务器端相互沟通:Socket类

1、构造方法

2、常用方法

六、IP地址:InetAddress类

七、测试demo

1、模拟客户端Client

2、模拟服务器端Server


一、Socket概念

Socket使用TCP,提供两台计算机之间的通信,主要用于描述IP和端口,在建立网络连接时使用。


二、Socket基本操作

  • 连接远程机器
  • 发送、接受数据
  • 关闭连接
  • 绑定端口
  • 监听入站信息
  • 在绑定端口上接受来自远程机器的连接

其中Socket类(客户端和服务器均可使用)提供了前3个操作方法;而SeverSocket类(仅服务器使用)提供后3个操作方法,等待客户端的连接。

当本地主机与远程主机建立连接后,两端就会从创建的Socket中得到输入流和输出流,然后使用这两个流相互发送数据。


三、Socket建立通信原理

Socket所在位置介于应用层和传输层之间,如下图:

首先服务端初始化ServerSocket,然后对指定的端口进行绑定,对端口进行监听,通过调用accept() 阻塞,接着循环等待客户端发起连接;当连接成功时,两端都会创建一个 Socket 对象,然后将两端的输入流和输出流相互交叉连接,接下来客户端和服务器端就可以通信了:

  •  具体步骤

  1. 服务器端实例化一个 java.net.ServerSocket 对象
  2. 服务器端调用 ServerSocket.accept() 方法,从此阻塞等待直到有客户端发起连接(服务器等待中....)
  3. 客户端1实例化一个Socket对象,指定服务器名称和端口号请求连接
  4. 如果通信建立,则在客户端创建一个Socket对象能够与服务器进行通信
  5. 此时服务器端的accept()方法返回一个新的socket引用,与客户端socket连接

接下来就可以使用IO流进行通信了。两端输入流和输出流的连接关系为:

  • 客户端输出流 --> 服务器端输入流
  • 客户端输入流 --> 服务器端输出流

四、服务器端:ServerSocket类

1、构造方法

java.net.Server类有四个构造方法用于创建服务器套接字,参数个数为0~3:

1public ServerSocket (int port) throws IOException
创建绑定到特定端口的服务器套接字
2public ServerSocket (int port, int backlog) throws IOException
利用指定的 backlog 创建服务器套接字并将其绑定到指定的本地端口号
3public ServerSocket (int port, int backlog, InetAddress address) throws IOException
使用指定的端口、监听backlog、要绑定到的本地 IP 地址创建服务器
4public ServerSocket() throws IOException
创建非绑定服务器套接字(如果此方法使用时没有抛出异常,就意味着程序已经成功绑定到指定的端口,并且监听客户端请求。感觉可以用来检测是否绑定成功

2、常用方法

1public int getLocalPort()
返回此套接字监听的端口
2public Socket accept() throws IOException
监听并接受此套接字的连接
3public void setSoTimeout (int timeout)
通过指定超时值启用/禁用 SO_TIMEOUT(以ms为单位)
4public void bind(SocketAddress host, int backlog)
将 ServerSocket 绑定到特定地址(IP 地址和端口号)

五、客户端与服务器端相互沟通:Socket类

Socket类与ServerSocket类不同,它可以在两端使用以确保两端连接与通信。客户端获取一个Socket实例化对象,而服务器端通过accept方法获取一个Socket对象返回值。 

1、构造方法

Socket构造方法返回并不是简单地实例化对象,而是尝试连接到指定的服务器和端口:

1public Socket (String host, int port) throws UnknownHostException, IOException
创建一个流套接字并将其连接到指定主机上的指定端口号
2public Socket (InetAddress host, int port) throws IOException
创建一个流套接字并将其连接到指定 IP 地址的指定端口号
3public Socket (String host, int port, InetAddress localAddress, int localPort) throws IOException
创建一个套接字并将其连接到指定远程主机上的指定远程端口
4public Socket (InetAddress host, int port, InetAddress localAddress, int localPort) throws IOException
创建一个套接字并将其连接到指定远程地址上的指定远程端口
5public Socket ()
通过系统默认类型的 SocketImpl 创建未连接套接字

2、常用方法

以下为一些客户端和服务器端共享的方法:

1public void connect(SocketAddress host, int timeout) throws IOException
将此套接字连接到服务器,并指定一个超时值
2public InetAddress getInetAddress()
返回套接字连接的地址
3public int getPort()
返回此套接字连接的远程端口
4public int getLocalPort()
返回此套接字绑定的本地端口
5public SocketAddress getRemoteSocketAddress()
返回此套接字连接的端点地址(未连接返回 null)
6public InputStream getInputStream() throws IOException
返回此套接字的输入流
7public OutputStream getOutputStream() throws IOException
返回此套接字的输出流
8public void close() throws IOException
关闭此套接字

六、IP地址:InetAddress类

互联网协议地址,也称作IP地址, 是网际协议中用于标识发送或接收数据报的设备的一串数字。在Socket编程中用得较多的方法如下:

1static InetAddress getByAddress(byte[] addr)
在给定原始 IP 地址的情况下返回 InetAddress 对象
2static InetAddress getByAddress(String host, byte[] addr)
根据提供的主机名和 IP 地址创建 InetAddress
3static InetAddress getByName(String host)
在给定主机名的情况下确定主机 IP 地址
4String getHostAddress() 
返回 IP 地址字符串(文本表现)
5String getHostName() 
获取此 IP 地址的主机名
6static InetAddress getLocalHost()
返回本地主机
7String toString()
将此 IP 地址转换为String格式

七、测试demo

1、模拟客户端Client

通过 Socket 连接到服务器并发送一个请求,然后等待一个响应:

public class GreetingClient {
    public static void main(String [] args) {
        String serverName = args[0];
        int port = Integer.parseInt(args[1]);  // 端口号
        try
        {
            System.out.println("连接到主机:" + serverName + " ,端口号:" + port);

            // 创建一个套接字并将其连接到指定主机上的指定端口号
            Socket client = new Socket(serverName, port);

            // 获取套接字端口地址
            System.out.println("远程主机地址:" + client.getRemoteSocketAddress());

            // 输出流(将会在服务器端输出)
            OutputStream outToServer = client.getOutputStream();
            DataOutputStream out = new DataOutputStream(outToServer);
            out.writeUTF("Hello from " + client.getLocalSocketAddress());

            //输入流
            InputStream inFromServer = client.getInputStream();
            DataInputStream in = new DataInputStream(inFromServer);
            System.out.println("服务器响应: " + in.readUTF());

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

2、模拟服务器端Server

使用 Socket 来监听一个指定的端口

public class GreetingServer extends Thread {
    private ServerSocket serverSocket;

    public GreetingServer(int port) throws IOException {
        serverSocket = new ServerSocket(port);
        serverSocket.setSoTimeout(10000);  // 设置等待时间为10s
    }

    public void run() {
        while(true) {
            try {
                System.out.println("等待远程连接,端口号为:" + serverSocket.getLocalPort() + "...");

                // 监听并接收套接字连接
                Socket server = serverSocket.accept();
                System.out.println("远程主机地址:" + server.getRemoteSocketAddress());

                // 输入流
                DataInputStream in = new DataInputStream(server.getInputStream());
                System.out.println(in.readUTF());

                // 输出流(将会在客户端输出)
                DataOutputStream out = new DataOutputStream(server.getOutputStream());
                out.writeUTF("谢谢连接我:" + server.getLocalSocketAddress() + "\nGoodbye!");

                server.close();
            }catch(SocketTimeoutException s) {  //如果时间耗尽
                System.out.println("Socket timed out!");
                break;  // 886退出程序
            }catch(IOException e) {
                e.printStackTrace();
                break;
            }
        }
    }
    public static void main(String [] args) {
        int port = Integer.parseInt(args[0]);  // 端口号
        try {
            Thread t = new GreetingServer(port);
            t.run();  // 开个线程
        }catch(IOException e) {
            e.printStackTrace();
        }
    }
}

接下来分俩个终端同时运行两个程序,首先本地1先输出“等待....”,接着我们在本地2运行程序输入主机名和同一个端口号6066,二者将会连接成功,并接着输出对应信息:

耶!客户端和服务器端的输入和输出流的连接,使得两个端口的信息成功交互输出!(红色部分就是交换内容)

写的中间出现了好多异常,也都在调试中一个个被消杀掉了。

Java异常,一生之敌 (T-T)

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

颜 然

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值