厦门有什么网站制作公司黄页引流推广
BIO模式下的基础工作机制
- 服务器端启动一个 ServerSocket,注册端口,调用accpet方法监听客户端的Socket连接。
- 客户端启动 Socket 对服务器进行通信,默认情况下服务器端需要对每个客户 建立一个线程与之通讯
实例:
- 网络编程的基本模型是Client/Server模型,也就是两个进程之间进行相互通信,其中服务端提供位置信(绑定IP地址和端口),客户端通过连接操作向服务端监听的端口地址发起连接请求,基于TCP协议下进行三次握手连接,连接成功后,双方通过网络套接字(Socket)进行通信。
- 传统的同步阻塞模型开发中,服务端ServerSocket负责绑定IP地址,启动监听端口;客户端Socket负责发起连接操作。连接成功后,双方通过输入和输出流进行同步阻塞式通信。
- 基于BIO模式下的通信,客户端 - 服务端是完全同步,完全耦合的。
BIO模式下的多发和多接收数据的实例
java提供了一个包,java.net 下的类都是用于网络通信
java提供了基于套接字socket的网络通信模式(基于此种模式可以实现TCP通信)
创建客户端的过程:
1、 创建一个socket的通信通道,建立与服务端的连接 从socket管道中得到一个字节输出流
2、把字节流改装成自己需要的流进行数据的发送创建服务端的过程:
1、 注册端口
2、开始等待客户端的连接
3、得到一个端到端的socket管道
4、从socket管道中得到一个字节输出流
5、把字节输出流包装成其他所需的流进行数据的传输
Sever端
package com.qst.Test1;import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;public class Server {public static void main(String[] args) {System.out.println("server starting.....");try {// 注册端口ServerSocket socket = new ServerSocket(9999);// 开始在这里暂停等待接收客户端的连接,得到一个端到端的Socket管道Socket ss = socket.accept();// 改装接收输入数据流BufferedReader reader = new BufferedReader(new InputStreamReader(ss.getInputStream()));String name;// 打印数据while((name = reader.readLine()) != null) {System.out.println(name);}ss.close();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}
Client 端
package com.qst.Test1;import java.io.IOException;
import java.io.PrintStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;public class Client {public static void main(String[] args) throws IOException, IOException {// 创建一个Socket的通信管道,请求与服务端的端口连接。Socket socket = new Socket("127.0.0.1",9999);// 改装流(获取一个字节的输出流)PrintStream stream = new PrintStream(socket.getOutputStream());Scanner sc = new Scanner(System.in);while(true) {String name = sc.nextLine();// 写入stream.println("msg "+name);// 刷新stream.flush();}}}
虽然可以进行数据多发,但是服务端是单线程的,一次只能接收一条数据
BIO模式下接收多个客户端(引入线程的概念)
此时我们就需要在服务端引入线程了,处理多个客户端连接的请求,也就是说客户端每发起一个请求,服务端就创建一个新的线程来处理这个客户端的请求,这样就实现了一个客户端一个线程的模型
Client端
package com.qst.ThreadServer;import java.io.IOException;
import java.io.PrintStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;public class Client {public static void main(String[] args) throws IOException, IOException {Socket socket = new Socket("127.0.0.1",9999);PrintStream stream = new PrintStream(socket.getOutputStream());Scanner sc = new Scanner(System.in);while(true) {String name = sc.nextLine();stream.println("zs :"+name);stream.flush();}}}
Server端
package com.qst.ThreadServer;import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;public class Server {public static void main(String[] args) throws IOException {System.out.println("server starting ......");ServerSocket socket = new ServerSocket(9999);while (true) {Socket accept = socket.accept();new ServerThreadReader(accept).start();System.out.println(accept.getLocalSocketAddress()+"上线了");}}}
ServerThread端
package com.qst.ThreadServer;import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.Socket;public class ServerThreadReader extends Thread{private Socket socket;public ServerThreadReader(Socket socket) {this.socket = socket;}@Overridepublic void run() {try {BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));String msg;while((msg = reader.readLine()) != null) {System.out.println("msg "+ msg);}} catch (IOException e) {// TODO Auto-generated ce.printStackTrace();}}}
结论
- 1.每个Socket接收到,都会创建一个线程,线程的竞争、切换上下文影响性能;
- 2.每个线程都会占用栈空间和CPU资源;
- 3.并不是每个socket都进行IO操作,无意义的线程处理;
- 4.客户端的并发访问增加时。服务端将呈现1:1的线程开销,访问量越大,系统将发生线程栈溢出,线程创建失败,最终导致进程宕机或者僵死,从而不能对外提供服务。