【Java】ServerSocket的学习笔记
公司有本《Java网络编程》一直闲置在书架上,反正我对Socket方面不太懂,今天跟着书学习一番。
> 参考的优秀书籍
《Java网络编程》 --中国电力出版社
> 最简单的服务器端
当客户端连接进来,向客户端发送“welcome”以表咋程序员的亲切感~~
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket; public class SimpleServerSocket { public static void main(String[] args) {
ServerSocket ss = null;
Socket s = null;
OutputStreamWriter osw = null;
try {
ss = new ServerSocket(9000); s = ss.accept();
osw = new OutputStreamWriter(s.getOutputStream());
osw.write("welcome..." + System.getProperty("line.separator"));
osw.flush();
System.out.println("outputed."); } catch (IOException e) {
System.out.println("socket exception.");
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
CloseableCloser.close(osw);
CloseableCloser.close(s);
CloseableCloser.close(ss);
}
} }
有许多资源需要关闭,那就写一个小的工具类来关闭吧
import java.io.Closeable;
import java.io.IOException; public class CloseableCloser { public static void close(Closeable c) {
if (c == null) {
return;
} try {
c.close();
} catch (IOException e) {
// TODO Auto-generated catch block
System.out.println("exception when closing.");
e.printStackTrace();
}
} }
通过Linux telnet一下,看到反馈了。
当然用Windows telnet也一样的,只是Windows telnet跳了一个页面,不方便截图而已。
注意:如果服务端输出语句时没有加换行符,我在Linux、Windows测试时都没看到打印welcome哦。
telnet xx.xx.xx.xx 9000
Trying xx.xx.xx.xx...
Connected to xx.xx.xx.xx.
Escape character is '^]'.
welcome...
Connection closed by foreign host.
当然也可通过Java Socket编写客户端去连接
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.net.UnknownHostException; public class SimpleSocket { public static void main(String[] args) {
Socket s = null;
BufferedReader br = null;
String line = null;
try {
s = new Socket("127.0.0.1", 9000);
br = new BufferedReader(new InputStreamReader(s.getInputStream()));
while ((line = br.readLine()) != null) {
System.out.println(line);
} } catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
CloseableCloser.close(s);
} } }
> 提供持续的服务,同时处理好不同的异常
看上面的服务端程序,可以发现它只能处理一个任务,而服务端一般来说是提供持续的服务的嘛,那么我们加一个while true呗。
另外,与客户端交互的Socket的异常和ServerSocket的异常是不是需要分开处理一下呢?试想,你一定不想某一个业务出现异常了,导致整个服务端的服务都中止的。
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket; public class SimpleServerSocket { public static void main(String[] args) {
ServerSocket ss = null;
Socket s = null;
OutputStreamWriter osw = null;
try {
ss = new ServerSocket(9000); while (true) {
try {
s = ss.accept();
osw = new OutputStreamWriter(s.getOutputStream());
osw.write("welcome..." + System.getProperty("line.separator"));
osw.flush();
System.out.println("outputed."); } catch (IOException e) {
System.out.println("socket exception.");
// TODO Auto-generated catch block
e.printStackTrace(); } finally {
CloseableCloser.close(osw);
CloseableCloser.close(s);
}
} } catch (IOException e) {
System.out.println("server socket exception.");
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if (ss != null) {
CloseableCloser.close(ss);
}
}
} }
这样,你用多个客户端不断地连接,它都给你响应了。
> 并发地处理任务
上述的服务端代码有一段线程睡眠的代码用于模拟业务处理所需的时间的,我们把它的注解解开,然后用不同客户端连接,可以发现,程序在同一时间只能处理一个任务嘛。
而且,由于服务端同时只能处理一个请求,其他请求就堵塞了,操作系统会将请求同一端口的请求存储在一个先进先出的队列中,然而这个队列有长度限制。当然,这个限制各个操作系统不同。
不信,那么我们用Java多线程发送150个请求:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.net.UnknownHostException; public class MultipleSocket extends Thread { public static void main(String[] args) {
for (int i = 0; i < 150; i++) {
new MultipleSocket().start();
}
} public void run() {
Socket s = null;
BufferedReader br = null;
String line = null;
try {
System.out.println(this.getName() + " is started."); s = new Socket("127.0.0.1", 9000);
br = new BufferedReader(new InputStreamReader(s.getInputStream()));
while ((line = br.readLine()) != null) {
System.out.println(line);
} } catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
CloseableCloser.close(br);
CloseableCloser.close(s);
}
} }
不出意外,将报以下异常:
java.net.ConnectException: Connection refused: connect
at java.net.DualStackPlainSocketImpl.connect0(Native Method)
at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:79)
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:339)
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:200)
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:182)
那么我们就转为线程处理呗!
这里换为多线程处理,同时限制同时最多处理2个线程(需要限制几个线程数,自己设置哦)。
为什么要限制线程数量呢?如果同时许多了客户端连接,超过一定数量,最直接的结果就是内存耗尽了。
关于如何限制线程数量,可以参考以前的博文:【多线程】并发执行指定数量的线程
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; public class SimpleServerSocket { public static void main(String[] args) {
ServerSocket ss = null;
Socket s = null;
OutputStreamWriter osw = null;
ExecutorService es = Executors.newFixedThreadPool(2); try {
ss = new ServerSocket(9000); while (true) {
s = ss.accept();
es.execute(new BusinessThread(s));
} } catch (IOException e) {
System.out.println("server socket exception.");
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if (ss != null) {
CloseableCloser.close(ss);
}
}
} }
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.util.concurrent.TimeUnit; public class BusinessThread implements Runnable { Socket s = null; public BusinessThread(Socket s) {
super();
this.s = s;
} public void run() {
OutputStreamWriter osw = null;
try {
osw = new OutputStreamWriter(s.getOutputStream());
osw.write("welcome..." + System.getProperty("line.separator"));
osw.flush();
System.out.println("outputed."); // 模拟这里的业务进行得很慢
try {
TimeUnit.SECONDS.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} } catch (IOException e) {
System.out.println("socket exception.");
// TODO Auto-generated catch block
e.printStackTrace(); } finally {
CloseableCloser.close(osw);
CloseableCloser.close(s);
}
} }
【Java】ServerSocket的学习笔记的更多相关文章
- Java:NIO 学习笔记-3
Java:NIO 学习笔记-3 根据 黑马程序员 的课程 JAVA通信架构I/O模式,做了相应的笔记 3. JAVA NIO 深入剖析 在讲解利用 NIO 实现通信架构之前,我们需要先来了解一下 NI ...
- Java:NIO 学习笔记-2
Java:NIO 学习笔记-2 上一篇 NIO 学习笔记-1 看了 尚硅谷 的相应教程,此处又对比看了 黑马程序员 的课程 JAVA通信架构I/O模式,做了相应的笔记 前言 在 Java 的软件设计开 ...
- Java:NIO 学习笔记-1
Java:NIO 学习笔记-1 说明:本笔记是根据bilibili上 尚硅谷 的课程 NIO视频 而做的笔记 主要内容 Java NIO 简介 Java NIO 与 IO 的主要区别 缓冲区(Buff ...
- JAVA GUI编程学习笔记目录
2014年暑假JAVA GUI编程学习笔记目录 1.JAVA之GUI编程概述 2.JAVA之GUI编程布局 3.JAVA之GUI编程Frame窗口 4.JAVA之GUI编程事件监听机制 5.JAVA之 ...
- Java多线程技术学习笔记(二)
目录: 线程间的通信示例 等待唤醒机制 等待唤醒机制的优化 线程间通信经典问题:多生产者多消费者问题 多生产多消费问题的解决 JDK1.5之后的新加锁方式 多生产多消费问题的新解决办法 sleep和w ...
- Java安全防御学习笔记V1.0
Java安全防御学习笔记V1.0http://www.docin.com/p-766808938.html
- java之jvm学习笔记六-十二(实践写自己的安全管理器)(jar包的代码认证和签名) (实践对jar包的代码签名) (策略文件)(策略和保护域) (访问控制器) (访问控制器的栈校验机制) (jvm基本结构)
java之jvm学习笔记六(实践写自己的安全管理器) 安全管理器SecurityManager里设计的内容实在是非常的庞大,它的核心方法就是checkPerssiom这个方法里又调用 AccessCo ...
- java之jvm学习笔记三(Class文件检验器)
java之jvm学习笔记三(Class文件检验器) 前面的学习我们知道了class文件被类装载器所装载,但是在装载class文件之前或之后,class文件实际上还需要被校验,这就是今天的学习主题,cl ...
- java之jvm学习笔记五(实践写自己的类装载器)
java之jvm学习笔记五(实践写自己的类装载器) 课程源码:http://download.csdn.net/detail/yfqnihao/4866501 前面第三和第四节我们一直在强调一句话,类 ...
- java之jvm学习笔记四(安全管理器)
java之jvm学习笔记四(安全管理器) 前面已经简述了java的安全模型的两个组成部分(类装载器,class文件校验器),接下来学习的是java安全模型的另外一个重要组成部分安全管理器. 安全管理器 ...
随机推荐
- Oracle游标整理二
1.概念 游标是指向SQL处理的内存区的句柄或指针.当使用一个PL/SQL块来执行DML语句或只返回一行结果的SELECT语句时,系统将自动创建一个隐式游标.如果SQL语句返回多个结果,就必须 ...
- 夺命雷公狗ThinkPHP项目之----企业网站24之网站前台获取当前栏目和顶级栏目
我们现在要实现的是取出网站当前栏目名称和顶级分类名称,如下所示: 列表页的和单页的不能总是写死的吧?? 我能就要想办法去让他变活的才可以解决问题噢,我们已经有了他的cate_id ,然后我们就可以通过 ...
- Power Gating的设计(模块二)
针对lower power的验证,由cpf/upf来建模,包括: 1)power gating的功能模型(在power gate之后将output force为x) 2)isolation功能模型: ...
- archlinux安装输入法需要的包及archlinux无法使用输入法的解决
所需的包: fcitx #这货应该是主要的程序 fcitx-configtool #图形化的配置工具,非必须 fcitx-gtk2 fcitx-gtk3 fcitx-qt4 fcitx-qt5 fci ...
- OpenStack 计算节点删除
前提 计算节点中一个僵尸计算节点存在,而里面的CPU数目在总物理CPU中,导致认为当前能创建实例.而实际没有这么多资源. 其中node-11为僵尸节点. 原因 删除计算节点不能直接格式化该服务器,否则 ...
- React的一个简单示例
首发:个人博客,更新&纠错&回复 React的核心是定义组件类,组件有三个要素:状态.行为.界面. 1.渲染状态到界面:状态由组件对象的state属性持有,从状态到界面的渲染工作由组件 ...
- XMl的解析
MainActivitypackage com.example.secondweek_test2; import java.io.BufferedInputStream; import java.io ...
- 前后台数据传输两种方式:servlet、Controller
1.Servlet: 1.1从jsp页面跳转到Servlet控制器中,通过request.getParameter()来获取参数. 1.2// 把注册成功的用户对象保存在session中 ...
- linux设备驱动归纳总结(四):3.抢占和上下文切换【转】
本文转载自:http://blog.chinaunix.net/uid-25014876-id-65711.html linux设备驱动归纳总结(四):3.抢占和上下文切换 xxxxxxxxxxxxx ...
- TI CC254x BLE教程 4
TI的CC254x芯片 1. SoC 2. RF收发器+8051MCU 128/256KB Code空间. 3. Master或者Slave 4. 可编程flash 5. 8KB SRAM 6. 全软 ...