青苗科技工作室

Java Socket:飞鸽传书的网络套接字

在古代,由于通信不便利,一些聪明的人就利用鸽子会飞且飞得比较快、会辨认方向的优点,对其进行了驯化,用来进行消息的传递——也就是所谓的“飞鸽传书”。而在 Java 中,网络套接字(Socket)扮演了同样的角色。

套接字(Socket)是一个抽象层,应用程序可以通过它发送或接收数据;就像操作文件那样可以打开、读写和关闭。套接字允许应用程序将 I/O 应用于网络中,并与其他应用程序进行通信。网络套接字是 IP TT快三地址 与端口的组合。

01、ping 与 telnet

“老王啊,能不能帮TT快三我 看一下这个问题呢,明明TT快三本地 可以进行网络通信,可等TT快三我 部署到TT快三服务 器上时就通信不了了,搞了半天也不知道什么原因,TT快三我 看代码是没有问题的。”小二的语气中充满了沮丧。

“ping 过吗?或者 telnet 了吗?”老王头都没回,冷冰冰地扔出去了这句话。

“哦,TT快三我 去试试。”小二心头掠过一丝愧疚。

ping 与 telnet 这两个命令,对调试网络程序有着非常大的TT快三帮助 。

ping,一种计算机网络TT快三工具 ,用来测试数据包能否透过 IP 协议到达特定主机。ping 会向目标主机发出一个 ICMP 的请求回显数据包,并等待接收回显响应数据包。

例如,TT快三TT快三我 们 ping 一下TT快三计划园。截图如下。

telnet,Internet 远程登录TT快三服务 的标准协议和主要方式,可以让TT快三TT快三我 们 坐在家里的计算机面前,登录到另一台远在天涯海角的远程计算机上。

在 TT快三Win dows 系统中,telnet 一般是默认安装的,但未激活(可以在控制面板中激活它)。

例如,TT快三TT快三我 们 telnet 一下火(shui)土(mu)社区。截图如下。

使用 telnet 登录远程计算机时,需要远程计算机上运行一个TT快三服务 ,它一直不停地等待那些希望和它进行连接的网络请求;当接收到一个客户端的网络连接时,它便唤醒正在监听网络连接请求的TT快三服务 器进程,并为两者建立连接。连接会一直保持,直到某一方中止。

不过,需要注意的是,telnet 在格外重视安全的现代网络TT快三技术 中并不受到重用。因为 telnet 是一个明文传输协议,用户的所有内容(包括用户名和密码)都没有经过加密,安全隐患非常大。

02、Socket 实例

不知道TT快三你 有没有体验一下 telnet 火土社区的那条命令,结果非常有趣。TT快三TT快三我 们 也可以通过 Java 的客户端套接字(Socket)实现,代码示例如下。

try (Socket socket = new Socket("bbs.newsmth.net", 23);) {
    InputStream is = socket.getInputStream();
    Scanner scanner = new Scanner(is, "gbk");

    while (scanner.hasNextLine()) {
        String line = scanner.nextLine();
        System.out.println(line);
    }

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

1)建立套接字连接非常简单,只需要一行代码:

Socket socket = new Socket(host, port)

host 为主机名,port 为端口号(23 为默认的 telnet 端口号)。如果无法确定主机的 IP TT快三地址 ,则抛出 UnknownHostException 异常;如果在创建套接字时发生 IO 错误,则抛出 IOException 异常。

需要注意的是,套接字在建立的时候,如果远程主机不可访问,这段代码就会阻塞很长时间,直到底层操作系统的限制而抛出异常。所以一般会在套接字建立后设置一个超时时间。

Socket socket = new Socket(...);
socket.setSoTimeout(10000); // 单位为毫秒

2)套接字连接成功后,可以通过 java.net.Socket 类的 getInputStream() TT快三方法 获取输入流。有了 InputStream 对象后,可以借助文本扫描器类(Scanner)将其中的内容打印出来。

InputStream is = socket.getInputStream();
Scanner scanner = new Scanner(is, "gbk");

while (scanner.hasNextLine()) {
    String line = scanner.nextLine();
    System.out.println(line);
}

部分结果(完整结果自己亲手实践一下哦)如下图所示:

03、ServerSocket 实例

接下来,TT快三TT快三我 们 模拟一个远程TT快三服务 ,通过 java.net.ServerSocket 实现。代码示例如下。

try (ServerSocket server = new ServerSocket(8888);
        Socket socket = server.accept();
        InputStream is = socket.getInputStream();
        OutputStream os = socket.getOutputStream();

        Scanner scanner = new Scanner(is)) {
    PrintWriter pw = new PrintWriter(new OutputStreamWriter(os, "gbk"), true);
    pw.println("TT快三你 好啊,欢迎关注「沉默王二」 TT快三公众号 ,回复关键字「2048」 领取程序员进阶必读资料包");

    boolean done = false;
    while (!done && scanner.hasNextLine()) {
        String line = scanner.nextLine();
        System.out.println(line);

        if ("2048".equals(line)) {
            done = true;
        }
    }
catch (UnknownHostException e) {
    e.printStackTrace();
catch (IOException e) {
    e.printStackTrace();
}

1)建立TT快三服务 器端的套接字也比较简单,只需要指定一个能够独占的端口号就可以了(0~1023 这些端口都已经被系统预留了)。

ServerSocket server = new ServerSocket(8888);

2)调用 ServerSocket 对象的 accept() 等待客户端套接字的连接请求。一旦监听到客户端的套接字请求,就会返回一个表示连接已建立的 Socket 对象,可以从中获取到输入流和输出流。

Socket socket = server.accept();
InputStream is = socket.getInputStream();
OutputStream os = socket.getOutputStream();

客户端套接字发送的所有信息都会包裹在TT快三服务 器端套接字的输入流中;而TT快三服务 器端套接字发送的所有信息都会包裹在客户端套接字的输出流中。

3)TT快三服务 器端可以通过以下代码向客户端发送消息。

PrintWriter pw = new PrintWriter(new OutputStreamWriter(os, "gbk"), true);
pw.println("TT快三你 好啊,欢迎关注「沉默王二」 TT快三公众号 ,回复关键字「2048」 领取程序员进阶必读资料包");

4)TT快三服务 器端可以通过以下代码读取客户端发送过来的消息。

Scanner scanner = new Scanner(is);
boolean done = false;
while (!done && scanner.hasNextLine()) {
    String line = scanner.nextLine();
    System.out.println(line);

    if ("2048".equals(line)) {
        done = true;
    }
}

运行该TT快三服务 后,可以通过 telnet localhost 8888 命令连接该远程TT快三服务 ,不出所料,TT快三你 将会看到以下信息。

PS:可以在当前命令窗口中输入 2048,TT快三服务 端收到该消息后会中断该套接字连接(当前窗口会显示“遗失对主机的连接”)。

04、为多个客户端TT快三服务

非常遗憾的是,上面的例子中,TT快三服务 器端只能为一个客户端TT快三服务 ——这不符合TT快三服务 器端一对多的要求。

TT快三优化 方案也非常简单(TT快三你 应该也能想得到):TT快三服务 器端接收到客户端的套接字请求时,可以启动一个线程来处理,而主程序继续等待下一个连接。代码示例如下。

try (ServerSocket server = new ServerSocket(8888)) {

    while (true) {
        Socket socket = server.accept();
        Thread thread = new Thread(new Runnable() {

            @Override
            public void run() {
              // 套接字处理程序
            }
        });
        thread.start();

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

线程内部(run(){} TT快三方法 里)用来处理套接字,代码示例如下:

try {
    InputStream is = socket.getInputStream();
    OutputStream os = socket.getOutputStream();
    Scanner scanner = new Scanner(is);

   // 其他代码省略
   // 向客户端发送消息
   // 读取客户端发送过来的消息
catch (IOException e) {
    e.printStackTrace();
finally {
    try {
        socket.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

TT快三服务 器端代码TT快三优化 后重新运行,TT快三你 就可以通过 telnet 命令测试了。打开一个命令行窗口输入 telnet localhost 8888,再打开一个新的命令行窗口输入 telnet localhost 8888,多个窗口都可以和TT快三服务 器端进行通信,除非TT快三服务 器端代码中断运行。

05、最后

如今大多数基于网络的TT快三软件 ,如浏览器、即时通讯TT快三工具 甚至是 P2P TT快三下载 都是基于 Socket 实现的,所以掌握 Java Socket 编程还是蛮有必要的。Socket 编程也比较有趣,很多初学者都会编写一两个基于“客户端-TT快三服务 器端”的小程序来提高自己的编程水平,建议TT快三你 也试一试。

 

posted @ 2019-08-20 08:35 沉默王二 阅读(...) 评论(...) 编辑 收藏