【开发经验】java socket编程详解

【开发经验】java socket编程详解前言​ 在大多数的java项目中,使用开发者直接使用socket的场景并不多。但是目前众多框架的底层中,都会有socket的身影。此示例一下java原始的socket编程,并通过telnet进行通讯。1、功能实现如上图所示,主要实现服务器开启服务,每个客户端链接时都分配一个新的线程与其通讯。2、服务端代码:importjava.io.InputStream;importjava.net.ServerSocket;importjava.net.Socket;importjava.u

大家好,又见面了,我是你们的朋友全栈君。

前言

​ 在大多数的java项目中,使用开发者直接使用socket的场景并不多。但是目前众多框架的底层中,都会有socket的身影。此示例一下java原始的socket编程,并通过telnet进行通讯。

1、功能实现

image-20210409172945554

如上图所示,主要实现服务器开启服务,每个客户端链接时都分配一个新的线程与其通讯。

2、服务端代码:


import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class BIOServer { 
   
    public static void main(String[] args) throws Exception { 
   
        //创建线程池
        ExecutorService newCachedThreadPool = Executors.newCachedThreadPool();

        //创建ServerSocket
        ServerSocket serverSocket = new ServerSocket(6666);

        System.out.println("服务器启动了");

        while (true) { 
   

            System.out.println("线程信息 id =" + Thread.currentThread().getId() + " 名字=" + Thread.currentThread().getName());
            //监听,等待客户端连接
            System.out.println("等待连接....");
            final Socket socket = serverSocket.accept();
            System.out.println("连接到一个客户端");

            //就创建一个线程,与之通讯(单独写一个方法)
            newCachedThreadPool.execute(new Runnable() { 
   
                public void run() { 
    //我们重写
                    //可以和客户端通讯
                    handler(socket);
                }
            });

        }
    }
    //编写一个handler方法,和客户端通讯
    public static void handler(Socket socket) { 
   

        try { 
   
            System.out.println("线程信息 id =" + Thread.currentThread().getId() + " 名字=" + Thread.currentThread().getName());
            byte[] bytes = new byte[1024];
            //通过socket 获取输入流
            InputStream inputStream = socket.getInputStream();
            //循环的读取客户端发送的数据
            while (true) { 
   
                System.out.println("线程信息 id =" + Thread.currentThread().getId() + " 名字=" + Thread.currentThread().getName());
                System.out.println("read....");
               int read =  inputStream.read(bytes);
               if(read != -1) { 
   
                   System.out.println(new String(bytes, 0, read
                   )); //输出客户端发送的数据
               } else { 
   
                   break;
               }
            }
        }catch (Exception e) { 
   
            e.printStackTrace();
        }finally { 
   
            System.out.println("关闭和client的连接");
            try { 
   
                socket.close();
            }catch (Exception e) { 
   
                e.printStackTrace();
            }

        }
    }
}

3、client代码


import java.io.*;
import java.net.Socket;

 
public class SocketClient
{ 
   
	public static void main(String[] args) throws InterruptedException { 
   
		try { 
   
			// 和服务器创建连接
			Socket socket = new Socket("localhost",6666);
			// 要发送给服务器的信息
			OutputStream os = socket.getOutputStream();
			PrintWriter pw = new PrintWriter(os);
			pw.write("我是客户端:您好server!~");
			pw.flush();
			socket.shutdownOutput();
			os.close();
			pw.close();
			socket.close();
		} catch (Exception e) { 
   
			e.printStackTrace();
		}
	}

}

先启动server,然后再启动client。server打印信息如下。

连接到一个客户端
线程信息 id =1 名字=main
等待连接…
线程信息 id =12 名字=pool-1-thread-1
线程信息 id =12 名字=pool-1-thread-1
read…
我是客户端:您好server!~
线程信息 id =12 名字=pool-1-thread-1
read…
关闭和client的连接

4、telnet连接

服务端启动之后,可以通过telnet进行连接。

image-20210409173539606

image-20210409173559043

连接成功之后,会跳入空白页面,通过 CTRL+]进入发送信息的页面。

image-20210409173650703

通过send命令发送信息。

image-20210409173726957

服务端打印信息如下

连接到一个客户端
线程信息 id =1 名字=main
等待连接…
线程信息 id =13 名字=pool-1-thread-2
线程信息 id =13 名字=pool-1-thread-2
read…
hello server
线程信息 id =13 名字=pool-1-thread-2
read…

可多启动几个命令行窗口,可发现其线程id不同。
通过socket通讯即可发现,每个连接都会占用一个线程。另外,在这种聊天的场景中,每个线程大部分时间都在等待信息的传输,都在阻塞在inputStream.read这段代码。因为每次发送信息之后,最后都会read...。如此,发现通过这种bio的方式会造成线程的浪费。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/156410.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 更改nginx端口_nginx 端口映射

    更改nginx端口_nginx 端口映射Postedby撒得一地on2015年8月25日innginx笔记nginx相关文章在web服务器中,不管是Apache还是Nginx,这些服务器默认占用的端口都是80端口。但是,有时候80端口被占用,或者一些其他原因,我们需要这些服务工作在非80端口上,那么如何修改Nginx默认端口,使其占用8089端口(或者其它非80端口),方法步骤如下:1.首先修改nginx根目录下的配置文件n…

    2025年10月7日
    3
  • 国内公共DNS_网速快的DNS

    国内公共DNS_网速快的DNS中国互联网络中心(推荐,安全又快速):1.2.4.8、210.2.4.8、101.226.4.6(电信及移动)、123.125.81.6(联通)阿里DNS:223.5.5.5、223.6.6.6googleDNS(不推荐,容易掉包,还很慢):8.8.8.8、8.8.4.4openDNS:208.67.222.222208.67.220.220208.67.222.220208.67….

    2025年9月24日
    7
  • 域名的url转发功能是什么_url和域名有什么区别

    域名的url转发功能是什么_url和域名有什么区别在网上找了很久,感觉还是米发快捷点,适用于域名注册下来但是个人网站还没完成暂时转发至博客的,或者想给博客弄个个性点的域名的工具:域名,米发帐号  原理:域名商解析到第三方平台服务器,第三方平台帮你转发到你的地址1. 在米发平台上添加域名2. 在米发平台上添加转发操作,   显性URL转发:只是跳转,网站显示的还是你跳转后的地址,不是你的域名隐性URL转发:网站显示的是你的域名,内容是你要跳转的…

    2022年10月19日
    3
  • 基于51单片机的八路抢答器设计_单片机八路抢答器课程设计

    基于51单片机的八路抢答器设计_单片机八路抢答器课程设计写一下寒假做的51小项目,本次是基于AT89C51的八路抢答器,课设水平难度。具体说明:硬件分为两部分,主持人主控部分和选手使用部分。可以实现:按动开始可以开启程序或者开启答题倒计时,按动复位可以实现归零;八个选手各有一个按键,按下即可抢答,与此同时,蜂鸣器响一秒钟,选手的LED点亮。在答题时间还剩十秒钟时,发出提示音,时间耗尽时,所有LED点亮,蜂鸣器鸣响。当抢答倒计时结束仍没有选手抢答,所有…

    2022年10月20日
    2
  • Pycharm 中导入模块

    Pycharm 中导入模块Pycharm中导入模块@TOC以PyQt5为例1、首先要在安装PyQt5。在windows中以管理员身份打开CRM,然后输入pipinstallpyqt5,安装好pyqt5后,还可以继续安装pyqt5的相关工具,命令pipinstallpyqt5-tools2、在Pycharm中安装pyqt5步骤:File->setting->project:***->p…

    2022年8月27日
    5
  • VMM TEST「建议收藏」

    VMM TEST「建议收藏」vmm_testisintroducedinvmm1.1.Toknowthevmmversionwhichyouareusing,usethiscommandvcs-R-sverilog-ntb_optsdtm        +incdir+$VMM_HOME/sv$VMM_HOME/sv/vmm_versions.svv

    2022年9月22日
    4

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号