黑马程序员--10.网络编程--06.【Clinet_Server通信原理】【TCP_客户端和服务端会话】【阻塞式方法的详解】
2013-08-29 00:02
736 查看
网络编程--6
C/S通信原理(Client/Server)
TCP客户端和服务端会话
阻塞式方法详解
----------- android培训、java培训、java学习型技术博客、期待与您交流! ------------1. C/S通信原理
1). 服务器端的特点
(1). 一个服务端的存在可以允许接入多个客户端(2). Server端和单个Client端通信过程
{1}. 服务端ServerSocket对象本身没有流对象, 但是客户端Socket对象本身有流对象。
{2}. 但是一旦某个客户端和服务端建立了连接之后,服务端会通过自身的accept方法获取到这个客户端的通信端点Socket对象的副本,并使用这个Socket副本和真实的客户端对象进行通信。
e.g.
ServerSocket ss =new ServerSocket(10003); Socket s =ss.accept();
Socket s=ss.accept();使得ServerSocket端点获取到了客户端Socket的副本
因此在服务端的程序仅仅是通过ServerSocket对象获取到连接进来的Client的Socket对象之后,便是用这个Socket进行通信。
2). C/S通信原理
一个Server端和多个Client端进行通信的原理。(1). 一个Server端和多个Client端的通信原理图
(2). 通信过程分析
[1]. 客户端Socket A对象向Server端发了一个请求。假设此时连接成功。Server端便会通过自身的accept()方法获取客户端A的副本Socket对象。
[2]. A对象本身有输入流对象in和输出流对象out,因此在Server端的A对象的副本同样也有in和out两个对象。
[3]. 从客户端A向服务端Server发送数据
客户端的A对象通过自身的out向Server端发送出数据,此时Server端使用A对象的副本的in对象进行数据的读取。
[4]. 客户端A从服务端Server读取数据
Server端向给客户端A发出回馈信息,就通过A的副本的输出流对象out发出信息。此时客户端A通过自身的输入流对象in将Server端发送给自己的反馈信息读取进来。
[5]. 如果此时客户端C也连接到Server端,那么通信过程也是Server端C的副本和客户端的对象C进行通信。
[6]. 每个客户端在服务器端都有一个映像来和自己进行通信,因此各自进行自己的通信,不会混淆。
2. TCP客户端和服务端会话
1). TCP客户端通信
(1). 客户端需求客户端先向服务器发送数据,之后再从服务器获取反馈信息并把反馈信息打印在控制台上。
(2). 客户端会话代码示例
import java.net.*; import java.io.*; class TcpClient2{ public static void main(String[] args)throws Exception{ //向服务器发送数据 Socketsocket =new Socket("127.0.0.1", 10004); OutputStreamout =socket.getOutputStream(); out.write("Hi Server, I amClient...".getBytes()); //从服务端接收数据 InputStreamin =socket.getInputStream(); byte[] buf =newbyte[1024]; int len = in.read(buf); System.out.println("Server replied: "+new String(buf, 0, len)); } }
2). TCP服务器端通信
(1). 服务端需求
服务端先从客户端接受数据,之后再向客户端发送相应的反馈信息。
(2). 服务端会话代码示例
import java.net.*; import java.io.*; class TcpServer2{ public static void main(String[] args)throws Exception{ //接受客户端的连接请求并读出客户端的信息 ServerSocketss =new ServerSocket(10004); SocketclientSocket =ss.accept(); Stringip =clientSocket.getInetAddress().getHostAddress(); System.out.println(ip+"...connected!"); InputStreamin =clientSocket.getInputStream(); byte[] buf =newbyte[1024]; int len =in.read(buf); System.out.println("The message sent from Clientis :"+new String(buf, 0, len)); Thread.sleep(5000); OutputStreamout =clientSocket.getOutputStream(); out.write(("Hi, welcome to my Home,Client:"+ ip).getBytes()); clientSocket.close(); ss.close(); } }
3). 演示并分析结果
(1). 先启动服务器端,再启动客户端
(2). 分析程序执行过程
[1]. Server端先运行,首先遇到accept()这个阻塞式方法暂停下来,等待外界对服务端进行连接请求。SocketclientSocket
=ss.accept();
[2]. Client端后运行,通过自身的OutputStream对象将数据发送给服务器端。之后Client的程序自己向下运行至读取服务器端反馈信息的位置:int
len = in.read(buf);。由于IO的read方法是阻塞式方法,因此客户端也停下来等待服务器端发送来的信息。
[3]. 当服务器端有数据发送到客户端的时候,此时阻塞式read()方法可以读到数据,阻塞结束,Client端的程序继续运行。
3. 阻塞式方法详解
1). 常见的阻塞式方法
【总结】学过的阻塞式方法{1}. IO流中的BufferedReader的readLine()方法
{2}. IO流中的InputStream的read(byte[])方法
{3}, UDP通信中的接收方的receive(Datagrampacket)方法
{4}. TCP通信中的服务器方的accept()方法
【结论】程序中遇见阻塞式方法的时候,如果满足阻塞式方法的阻塞条件,程序的运行就会暂停下来进行等待。一定记住阻塞式方法阻塞的条件。
2). IO中 Reader抽象父类中阻塞式read方法
(1). Reader中阻塞式的read方法(2). Reader中阻塞式read方法的原型
[1]. public
int read() throws IOException;
{1}. 功能:读一个单个字符
{2}. 返回值:以整数的形式返回被读到的字符(0~65535)
[2]. public
int read(char cbuf[])throws IOException;
和. public
int read(char cbuf[],int off,
int len)throws IOException;
{1}. 功能:将一组字符读到一个数组cbuf[]中
{2}. 返回值:返回读到的字符数
【注意】如果达到了流的末尾,以上三种read方法都会返回-1
(3). read()方法解除阻塞的条件
[1]. read()
当一个字符可以被读或者IO错误发生或者输入流达到了末端(标志就是返回-1)出现的时候,原本阻塞的情况就会被解除。
[2]. read(char cbuf[])和read(char cbuf[],int off,
int len)
当某种输入可用或者IO错误发生或者输入流达到了末端(标志就是返回-1)出现的时候,原本阻塞的情况就会被解除。
3). IO中BufferedReader类中阻塞式readLine方法
(1). 方法源码public String readLine()throws IOException {
return readLine(false);
}
[1]. 换行符和回车符
{1}. line feed:换行符 =====>
'\n'
{2}. carriagereturn:回车符 =====>'\r'
[2]. 行结束符
换行符、回车符或者回车符后面紧随换行符这三种情况组成的符号任一都是一种行结束符
[3]. 何谓一行文本?
一行文本被认为是以换行符 ('\n')或者回车符
('\r')或者回车符后面跟上换行符 ("\r\n")结尾的字符序列。
[4]. 方法的功能:可以读取一行文本
[3]. 方法的返回值
{1}. 返回仅仅包含该行文本内容但是不包含任何一种行结束符的字符串。
{2}. 由于readLine方法调用了read方法,所以当流达到了末尾的时候,read方法返回了-1,这个时候由于readLine方法返回值的类型是引用类型,所以readLine方法将返回值从-1映射成了null。
【结论】当达到了流的结尾的时候,readLine方法返回-1。
(2). readLine()方法解除阻塞的条件
[1]. 【注意】由于readLine方法中调用了fill方法,fill方法又调用了Reader的read方法,因此BufferedReader的readLine方法也同样是阻塞式的。
[2]. read方法解除阻塞的条件
当某种输入可用或者IO错误发生或者输入流达到了末端(标志就是返回-1)出现的时候,原本阻塞的情况就会被解除。
[3]. readLine方法解除阻塞的条件
当某种输入行可用或者IO错误发生或者输入流达到了末端(标志就是返回null)出现的时候,原本阻塞的情况就会被解除。
【注意】readLine能返回数据(也就是阻塞解除)的情况之一必须是有输入行数据(以换行符 ('\n')或者回车符
('\r')或者回车符后面跟上换行符 ("\r\n")结尾的字符序列)才能算为“某种输入行可用”。如果读到的字符序列中没有以上述的行结束符结尾,readLine方法就会一直在那等着行结束符的到来,也就会一直阻塞下去。
(3). IO流中Reader类中阻塞方法解除阻塞的条件总结
常用到的到的解除阻塞情况的条件
{1}. 可以读到字符或者字符数组(也叫输入可用)
{2}. 输入流达到了末端 (标志是方法返回-1或者null)
4). UDP通信中的接收方的receive(Datagrampacket)方法
(1). 方法原型public
void receive(DatagramPacketp) throws IOException;
(2). receive()方法解除阻塞的条件
直到UDP的接收端的DatagramSocket接收到了数据报包,receive方法才会解除阻塞,方法才会继续执行。
5). TCP通信中的服务器的accept( )方法
(1). 方法原型public Socket accept()
throws IOException;
(2). receive()方法解除阻塞的条件
这个方法会一直阻塞直到有来自客户端的Socket和这个ServerSocket之间的连接被创建。
【结论】程序中遇见阻塞式方法的时候,如果满足阻塞式方法的阻塞条件,程序的运行就会暂停下来进行等待。一定记住阻塞式方法阻塞的条件。
----------- android培训、java培训、java学习型技术博客、期待与您交流! ------------
相关文章推荐
- 黑马程序员--10.网络编程--05.【TCP协议相关类】【InetSocketAddress类】【Socket类】【ServerSocket类】【TCP客户端和服务器端】
- Android网络编程之TCP通信----简单客户端与服务端通信
- linux下网络编程2:服务端和客户端进行TCP通信实例
- 网络编程_TCP_Socket通信原理_多个客户端_聊天室原理JAVA189-190
- 网络编程中客户端和服务端通信过程、原理及代码示例
- 黑马程序员_Java基础_网络编程_客户端服务端数据传输,交互,客户端请求服务原理,自定义浏览器,URL统一资源定位符
- 黑马程序员--10.网络编程--08.【C_S常见的“双卡”现象和解决--TCP复制文本文件示例II】【阻塞式循环的分析过程 ---总结】
- 26-网络编程-10-网络编程(TCP协议-客户端)
- 26-网络编程-12-网络编程(TCP协议-服务端和客户端交互)
- 客户端与服务端Socket通信原理详解
- 黑马程序员--10.网络编程--02.【网络传输三要素在Java中的体现】【TCP和UDP概念】【Socket基本概念】
- Java网络编程从入门到精通(28):获取ServerSocket信息的方法及FTP原理 推荐
- linux 网络编程之最简单的tcp通信服务端
- Linux网络编程之socket简单通信TCP--服务端代码
- .Net网络编程——使用TcpClient与TcpListener建立客户端与服务端连接
- Android网络编程之UDP通信----简单客户端与服务端通信
- Java网络编程(客户端和服务端原理)
- 黑马程序员-网络编程TCP练习(服务端)
- 基于TCP的网络编程之服务端和客户端之间的交流
- .Net网络编程——使用TcpClient与TcpListener建立客户端与服务端连接