- 浏览: 2652788 次
- 来自: 杭州
文章分类
- 全部博客 (1188)
- webwork (4)
- 网摘 (18)
- java (103)
- hibernate (1)
- Linux (85)
- 职业发展 (1)
- activeMQ (2)
- netty (14)
- svn (1)
- webx3 (12)
- mysql (81)
- css (1)
- HTML (6)
- apache (3)
- 测试 (2)
- javascript (1)
- 储存 (1)
- jvm (5)
- code (13)
- 多线程 (12)
- Spring (18)
- webxs (2)
- python (119)
- duitang (0)
- mongo (3)
- nosql (4)
- tomcat (4)
- memcached (20)
- 算法 (28)
- django (28)
- shell (1)
- 工作总结 (5)
- solr (42)
- beansdb (6)
- nginx (3)
- 性能 (30)
- 数据推荐 (1)
- maven (8)
- tonado (1)
- uwsgi (5)
- hessian (4)
- ibatis (3)
- Security (2)
- HTPP (1)
- gevent (6)
- 读书笔记 (1)
- Maxent (2)
- mogo (0)
- thread (3)
- 架构 (5)
- NIO (5)
- 正则 (1)
- lucene (5)
- feed (4)
- redis (17)
- TCP (6)
- test (0)
- python,code (1)
- PIL (3)
- guava (2)
- jython (4)
- httpclient (2)
- cache (3)
- signal (1)
- dubbo (7)
- HTTP (4)
- json (3)
- java socket (1)
- io (2)
- socket (22)
- hash (2)
- Cassandra (1)
- 分布式文件系统 (5)
- Dynamo (2)
- gc (8)
- scp (1)
- rsync (1)
- mecached (0)
- mongoDB (29)
- Thrift (1)
- scribe (2)
- 服务化 (3)
- 问题 (83)
- mat (1)
- classloader (2)
- javaBean (1)
- 文档集合 (27)
- 消息队列 (3)
- nginx,文档集合 (1)
- dboss (12)
- libevent (1)
- 读书 (0)
- 数学 (3)
- 流程 (0)
- HBase (34)
- 自动化测试 (1)
- ubuntu (2)
- 并发 (1)
- sping (1)
- 图形 (1)
- freemarker (1)
- jdbc (3)
- dbcp (0)
- sharding (1)
- 性能测试 (1)
- 设计模式 (2)
- unicode (1)
- OceanBase (3)
- jmagick (1)
- gunicorn (1)
- url (1)
- form (1)
- 安全 (2)
- nlp (8)
- libmemcached (1)
- 规则引擎 (1)
- awk (2)
- 服务器 (1)
- snmpd (1)
- btrace (1)
- 代码 (1)
- cygwin (1)
- mahout (3)
- 电子书 (1)
- 机器学习 (5)
- 数据挖掘 (1)
- nltk (6)
- pool (1)
- log4j (2)
- 总结 (11)
- c++ (1)
- java源代码 (1)
- ocr (1)
- 基础算法 (3)
- SA (1)
- 笔记 (1)
- ml (4)
- zokeeper (0)
- jms (1)
- zookeeper (5)
- zkclient (1)
- hadoop (13)
- mq (2)
- git (9)
- 问题,io (1)
- storm (11)
- zk (1)
- 性能优化 (2)
- example (1)
- tmux (1)
- 环境 (2)
- kyro (1)
- 日志系统 (3)
- hdfs (2)
- python_socket (2)
- date (2)
- elasticsearch (1)
- jetty (1)
- 树 (1)
- 汽车 (1)
- mdrill (1)
- 车 (1)
- 日志 (1)
- web (1)
- 编译原理 (1)
- 信息检索 (1)
- 性能,linux (1)
- spam (1)
- 序列化 (1)
- fabric (2)
- guice (1)
- disruptor (1)
- executor (1)
- logback (2)
- 开源 (1)
- 设计 (1)
- 监控 (3)
- english (1)
- 问题记录 (1)
- Bitmap (1)
- 云计算 (1)
- 问题排查 (1)
- highchat (1)
- mac (3)
- docker (1)
- jdk (1)
- 表达式 (1)
- 网络 (1)
- 时间管理 (1)
- 时间序列 (1)
- OLAP (1)
- Big Table (0)
- sql (1)
- kafka (1)
- md5 (1)
- springboot (1)
- spring security (1)
- Spring Boot (3)
- mybatis (1)
- java8 (1)
- 分布式事务 (1)
- 限流 (1)
- Shadowsocks (0)
- 2018 (1)
- 服务治理 (1)
- 设计原则 (1)
- log (0)
- perftools (1)
最新评论
-
siphlina:
课程——基于Python数据分析与机器学习案例实战教程分享网盘 ...
Python机器学习库 -
san_yun:
leibnitz 写道hi,我想知道,无论在92还是94版本, ...
hbase的行锁与多版本并发控制(MVCC) -
leibnitz:
hi,我想知道,无论在92还是94版本,更新时(如Puts)都 ...
hbase的行锁与多版本并发控制(MVCC) -
107x:
不错,谢谢!
Latent Semantic Analysis(LSA/ LSI)算法简介 -
107x:
不错,谢谢!
Python机器学习库
之前我以为java的socket很简单,不就是创建一个socketServet,然后不断的accept么?这种代码网上很多,基本流程是这样的:
ServerSocket server = new ServerSocket(8080); while (true) { Socket socket = server.accept(); InputStream input = socket.getInputStream(); int length = input.available(); if(length>0){ byte[] data = new byte[length]; input.read(data); String str = new String(data); String result = execute(str); OutputStream out = socket.getOutputStream(); out.write(("ok"+result+"\r\n").getBytes()); out.flush(); } socket.close(); }
虽然在做轮询,但accept()会阻塞,直到有新的客户端请求过来才会产生一个新的socket,然后读取数据,处理数据,最后关闭。基本流程是 accept()--->read()--->hand()--->close()。
代码看上去很简单,也能成功运行,但这段代码存在2个问题:
1. 一个socket只能处理一次就被关闭了,对于局域网的RPC来说这是很不划算的,很多时候我们希望能是长链接。处理流程变成accept()-->read()-->hand()-->read()-->hand()-->close()
2. 如果一个client在一个socket中连续发送两次数据,client端代码会报错,因为socket在处理玩第一次read数据之后就被server关闭了。
所以为了解决上面两个问题,我把这段代码修改一下,每个socket一个线程来处理:
class Channel implements Runnable { private Socket socket; private ServiceRegisterTester t ; public Channel(Socket socket,ServiceRegisterTester t ){ super(); this.socket = socket; this.t = t; } public void run() { try{ Socket socket = this.socket; while(true){ InputStream input = socket.getInputStream(); int length = input.available(); if(length>0){ byte[] data = new byte[length]; input.read(data); String str = new String(data); String result = t.test(str); OutputStream out = socket.getOutputStream(); out.write(("ok"+result+"\r\n").getBytes()); out.flush(); } } }catch(Exception e){ e.printStackTrace(); } } }
ServerSocket server = new ServerSocket(8080); while (true) { Socket socket = server.accept(); Channel chanenl = new Channel(socket,t); new Thread(chanenl).start(); }
这样每个socket都有一个单独的线程来处理,前面2个问题解决了!
但通过top观测发现java进程cpu占用非常高,都在做空转,每个socket都有线程在做轮询,这太伤害性能了吧,怎么才能让
socket.getInputStream();
也阻塞,让他能智能的读取到可用的数据才唤醒呢?
我相信netty也会遇到这个问题看看netty是如何解决的吧:
ChannelFactory factory = new OioServerSocketChannelFactory ( Executors.newCachedThreadPool(), Executors.newCachedThreadPool()); ServerBootstrap bootstrap = new ServerBootstrap (factory); DiscardServerHandler handler = new DiscardServerHandler(); ChannelPipeline pipeline = bootstrap.getPipeline(); pipeline.addLast("handler", handler); bootstrap.setOption("child.tcpNoDelay", true); bootstrap.setOption("child.keepAlive", true); bootstrap.bind(new InetSocketAddress(8080));
ChannelFactory需要两个线程池,一个是boss,一个是worker,boss只需要一个线程即可,worker可以根据合适的情况配置。当在执行 bootstrap.bind()的时候会启动boss线程,代码如下:
class OioServerSocketPipelineSink{ private void bind( OioServerSocketChannel channel, ChannelFuture future, SocketAddress localAddress) { Executor bossExecutor = ((OioServerSocketChannelFactory) channel.getFactory()).bossExecutor; bossExecutor.execute( new IoWorkerRunnable( new ThreadRenamingRunnable( new Boss(channel), "Old I/O server boss (channelId: " + channel.getId() + ", " + localAddress + ')'))); bossStarted = true; } }
OioServerSocketPipelineSink&Boss 是一个Runnable,其run方法如下:
while (channel.isBound()) { try { Socket acceptedSocket = channel.socket.accept(); try { ChannelPipeline pipeline = channel.getConfig().getPipelineFactory().getPipeline(); final OioAcceptedSocketChannel acceptedChannel = new OioAcceptedSocketChannel( channel, channel.getFactory(), pipeline, OioServerSocketPipelineSink.this, acceptedSocket); workerExecutor.execute( new IoWorkerRunnable( new ThreadRenamingRunnable( new OioWorker(acceptedChannel), "Old I/O server worker (parentId: " + channel.getId() + ", channelId: " + acceptedChannel.getId() + ", " + channel.getRemoteAddress() + " => " + channel.getLocalAddress() + ')'))); } catch (Exception e) { logger.warn( "Failed to initialize an accepted socket.", e); try { acceptedSocket.close(); } catch (IOException e2) { logger.warn( "Failed to close a partially accepted socket.", e2); } } }
可以看到Boss的职责就是轮询获取每个新请求Socket,立即交给workerExecutor处理,workerExecutor的逻辑单元封装在OioWorker,OioWorker的run方法如下:
public void run(){ final PushbackInputStream in = channel.getInputStream(); while (channel.isOpen()) { synchronized (channel.interestOpsLock) { while (!channel.isReadable()) { try { // notify() is not called at all. // close() and setInterestOps() calls Thread.interrupt() channel.interestOpsLock.wait(); } catch (InterruptedException e) { if (!channel.isOpen()) { break; } } } } byte[] buf; int readBytes; try { int bytesToRead = in.available(); if (bytesToRead > 0) { buf = new byte[bytesToRead]; readBytes = in.read(buf); } else { int b = in.read(); if (b < 0) { break; } in.unread(b); continue; } } catch (Throwable t) { if (!channel.socket.isClosed()) { fireExceptionCaught(channel, t); } break; } ChannelBuffer buffer; if (readBytes == buf.length) { buffer = ChannelBuffers.wrappedBuffer(buf); } else { // A rare case, but it sometimes happen. buffer = ChannelBuffers.wrappedBuffer(buf, 0, readBytes); } fireMessageReceived(channel, buffer); } // Setting the workerThread to null will prevent any channel // operations from interrupting this thread from now on. channel.workerThread = null; // Clean up. close(channel, succeededFuture(channel)); }
OioWorker里有一个非常重要的InputStream-PushbackInputStream,这个输入流能阻塞io,请看其read()方法的注释:“从此输入流中读取下一个数据字节。返回 0 到 255 范围内的 int 字节值。如果因流的末尾已到达而没有可用的字节,则返回值 -1。在输入数据可用、检测到流的末尾或者抛出异常前,此方法一直阻塞。”
netty就是利用这种方式来做轮询,而CPU又不至于空转。
相关推荐
Java Socket 实现 SMTP 协议发送邮件 Java Socket 是 Java 语言中用于实现网络编程的 API,通过 Socket,可以实现与远程服务器的通信。在这里,我们将使用 Java Socket 实现 SMTP 协议来发送邮件。 SMTP 协议简介 ...
2. 发送EHLO/HELO命令:向服务器表明身份,开始会话。 3. 如果服务器支持STARTTLS,发送STARTTLS命令,升级连接至TLS。如果支持SSL,直接创建SSLSocket并连接。 4. 身份验证:发送用户名和密码,通常使用AUTH PLAIN...
总的来说,通过Java的Socket实现EMAIL发送,虽然相对复杂,但有助于深入理解网络通信和SMTP协议的工作原理。如果你正在学习网络编程或者想要深入了解邮件发送的底层机制,这是一个非常有价值的实践项目。
总的来说,通过Java Socket实现SMTP邮件发送涉及到网络编程、SMTP协议理解、异常处理等多个知识点。这种技术在日常工作中非常实用,可以方便地集成到各种自动化任务或系统中,如定时发送报告、系统通知等。然而,...
SMTP(Simple Mail Transfer Protocol)是互联网上用于发送...如果你想要学习如何用Java发送邮件,理解这个项目中的`SMTPFrame.java`代码将非常有帮助,同时掌握SMTP协议的基本流程和Java Socket编程也是必不可少的。
Java Socket邮件发送是一种基于Java网络编程技术实现的邮件发送方式,主要利用了Socket类来连接SMTP(Simple Mail Transfer Protocol)服务器进行数据传输。SMTP是互联网上用于发送电子邮件的标准协议,而Java ...
Java中的Socket编程是一种网络通信机制,它允许两个网络应用程序之间进行双向通信。在这个"基于Java的简单socket邮件发送"实验中,我们将深入探讨如何利用Java的Socket类来构建一个基本的邮件发送系统。 首先,我们...
Java纯Socket发送邮件的知识点涉及了Java网络编程和电子邮件协议,特别是SMTP(Simple Mail Transfer Protocol)。在Java中,我们可以使用Socket类直接与SMTP服务器通信,实现邮件的发送。以下是对这个主题的详细...
【Java Socket 编程基础】 ...通过这个实验,学生将深入理解Java Socket编程的原理和实践,掌握SMTP协议的使用,以及如何在Java环境中创建用户友好的图形界面。这为后续的网络编程和应用开发打下了坚实的基础。
黑鲨helo-刷写第三方rec资源+步骤 实测支持安卓多版本 1----请使用本人实测的资源来刷写你的机型 2----资源可以支持不同安卓版本刷写第三方rec 3-----内含刷写资源和详细刷写教程步骤 4-----完美兼容当前此安卓...
基于Socket的邮件发送程序(Java编写) 在现代通信中,电子邮件是不可或缺的一部分,而Java作为一种广泛应用的编程语言,提供了多种方式来实现邮件的发送。本文将深入探讨如何使用Java的Socket编程实现SMTP(简单...
在Java中,我们可以使用Socket编程来实现SMTP客户端,从而发送邮件。下面我们将深入探讨如何使用Java Socket和SMTP协议来构建一个邮件发送程序。 首先,我们需要理解SMTP的工作流程: 1. **连接邮件服务器**:...
在Delphi中,通过Socket连接SMTP服务器,然后按照SMTP命令规范发送一系列指令,如HELO(你好)、MAIL FROM(发件人地址)、RCPT TO(收件人地址)、DATA(邮件内容)和QUIT(结束会话)。 在“Socket-IO模型全接触...
7. **编译与运行**:理解如何使用JDK的`javac`编译Java源代码,并用`java`命令运行可执行文件。 由于没有具体的代码内容,以上分析是基于一般Java项目的常规结构和功能做出的假设。实际项目中,Matheus Amilton de ...
- **确定多分组的编号**:按照从左至右的顺序,每个左括号遇到时即标记为一个新的分组开始,从1开始计数,后续分组编号依次递增。 #### 正则表达式外部引用分组 除了在正则表达式内部引用分组之外,有时还需要在...
Java提供JSSE(Java Secure Socket Extension)库来支持SSL/TLS,以及JASPI(Java Authentication and Security Service Provider Interface)来处理认证。 七、邮件解析与MIME标准 邮件内容可能包含多种格式,如...
通过将"hello"的WAR包部署到Glassfish服务器,初学者可以学习和理解如何在实际环境中运行和管理Java Web应用。 【标签】"war包"强调了这个压缩包的核心内容。WAR文件的结构有明确的规定,主要包括以下几个部分: 1...
使用Java Socket,我们可以创建一个连接到SMTP服务器的Socket实例,然后通过`PrintWriter`对象向服务器发送如"HELO"、"AUTH LOGIN"、"MAIL FROM:"、"RCPT TO:"和"DATA"等SMTP命令,最后发送邮件内容并关闭连接。...
标题 "r3_helo_" 暗示我们讨论的主题与Java Web开发有关,特别是使用Tomcat服务器和JSP(JavaServer Pages)技术进行文件解析。在这个场景中,"helo"可能是一个简写或者错误拼写,实际可能是“hello”,在编程中常...