三种常见构造器
Accept方法用于产生”阻塞”,直到接受到一个连接,并且返回一个客户端的Socket对象实例。”阻塞”是一个术语,它使程序运行暂时”停留”在这个地方,直到一个会话产生,然后程序继续;通常”阻塞”是由循环产生的。
. getInputStream方法获得网络连接输入,同时返回一个InputStream对象实例。
. getOutputStream方法连接的另一端将得到输入,同时返回一个OutputStream对象实例。
构造ServerSocket
ServerSocket() ~创建非绑定服务器套接字。
ServerSocket(int port) ~创建绑定到特定端口的服务器套接字。
ServerSocket(int port, int backlog) ~利用指定的 backlog 创建服务器套接字并将其绑定到指定的本地端口号。
ServerSocket(int port, int backlog, InetAddress bindAddr) ~使用指定的端口、侦听 backlog 和要绑定到的本地 IP 地址创建服务器。
服务端socket处理客户端socket连接是需要一定时间的。ServerSocket有一个队列,存放还没有来得及处理的客户端Socket,这个队列的容量就是backlog的含义。如果队列已经被客户端socket占满了,如果还有新的连接过来,那么ServerSocket会拒绝新的连接。也就是说backlog提供了容量限制功能,避免太多的客户端socket占用太多服务器资源。
http通信的三种方式
(1)servlets的方式 doPost(HttpServletRequest request, HttpServletResponse response)
(2)URLConnection 的方式:
URLConnection urlConnection = url.openConnection();
(2)使用HttpURLConnection实现POST请求
HttpURLConnection hp = (HttpURLConnection) url.openConnection();
(3)httpclient(get) {apache的架包来实现}
CloseableHttpClient client = HttpClients.createDefault();
HttpGet hg = new HttpGet("http://192.168.2.239:8080/afb/");
HttpResponse hr = client.execute(hg);
HttpEntity he = hr.getEntity();
String all = EntityUtils.toString(he);
(post)
CloseableHttpClient client = HttpClients.createDefault();
HttpGet hg = new HttpGet("http://192.168.2.239:8080/afb/");
List<BasicNameValuePair> parameters = new ArrayList<>(); parameters.add(new BasicNameValuePair("name", "张三")); //创建参数列表
post.setEntity(new UrlEncodedFormEntity(parameters, "utf-8")); 设置实体
HttpResponse hr = client.execute(hg);
HttpEntity he = hr.getEntity();
String all = EntityUtils.toString(he);
一旦创建了一个套接字实例,操作系统就会为其分配缓冲区以存放接收和要发送的数据。
就是在Socket的OutputStream上调用flush()方法,也不能保证数据能够立即发送到网络。真正的数据发送是由操作系统的TCP协议栈模块从缓冲区中取数据发送到网络来完成的。当有数据从网络来到时,TCP协议栈模块接收数据并放入接收缓冲区队列RecvQ,输入流InputStream通过read方法从RecvQ中取出数据。
(socket IO方面的)
BIO阻塞IO 新创建会为每一个socket请求分配一个线程,数量过多的时候会制约效率。
NIO维持一个通道管理器。内部以key-value的形式存储有当前连接的socket代表,轮询查询当前连接是否有通信任务,有就调用。具体流程:(并行变转盘了)
- Acceptor注册Selector,监听accept事件
- 当客户端连接后,触发accept事件
- 服务器构建对应的Channel,并在其上注册Selector,监听读写事件
- 当发生读写事件后,进行相应的读写处理
NIO的优缺点和BIO就完全相反了!性能高,不用一个连接就建一个线程,可以一个线程处理所有的连接!相应的,编码就复杂很多,从上面的代码就可以明显体会到了。还有一个问题,由于是非阻塞的,应用无法知道什么时候消息读完了,就存在了半包问题!
半包问题就是原来拆包传输数据的时候,集合的时候会根据顺序组装,没到会阻塞等待。NIO没有阻塞,可能会导致的数据错乱。需要自行处理。
Reactor模型
Reactor模型和AWT事件模型很像,就是将消息放到了一个队列中,通过异步线程池对其进行消费!
单线程模型:
多线程模型:
Reactor多线程模型就是将Handler中的IO操作和非IO操作分开,操作IO的线程称为IO线程,非IO操作的线程称为工作线程!这样的话,客户端的请求会直接被丢到线程池中,客户端发送请求就不会堵塞!
但是当用户进一步增加的时候,Reactor会出现瓶颈!因为Reactor既要处理IO操作请求,又要响应连接请求!为了分担Reactor的负担,所以引入了主从Reactor模型!
主Reactor用于响应连接请求,从Reactor用于处理IO操作请求!