网络程序设计 第二章 客户端Socket用法详解.

Slides:



Advertisements
Similar presentations
7.1 内置对象概述及分类 JSP 视频教学课程. JSP2.2 目录 1. 内置对象简介 1. 内置对象简介 2. 内置对象分类 2. 内置对象分类 3. 内置对象按功能区分 3. 内置对象按功能区分 4. 内置对象作用范围 4. 内置对象作用范围.
Advertisements

阻塞操作. 在 linux 里,一个等待队列由一个 wait_queue_head_t 类型的结构来描述 等待队列的初始化: static wait_queue_head_t testqueue; init_waitqueue_head(&testqueue);
3.2 Java的类 Java 类库的概念 语言规则——程序的书写规范 Java语言 类库——已有的有特定功能的Java程序模块
NAT与ICMP交互.
檔案處理.
Java的程式架構與基本觀念 Java語言的歷史 Java程式的開發環境 Java程式的架構 輸出與輸入物件之使用 工具使用方法介紹
第十讲 网络通信 1、网络基本概念 2、Java与Internet 3、使用InetAddress 4、使用URL 5、Socket通信
第十五章 网络编程.
网络程序设计 第二章 客户端Socket用法详解.
第二章 JAVA语言基础.
创意源自激情,技术成就梦想 畅翼创新俱乐部 2012年春俱乐部第三次技术培训 赵程.
目标 运用File类进行文件操作 理解流,标准输入/输出流的概念
实验4 基于Socket的C/S程序开发 实验目的
在PHP和MYSQL中实现完美的中文显示
第5章 异常处理 王德俊 上海交通大学继续教育学院.
2.1 基本資料型別 2.2 變數 2.3 運算式與運算子 2.4 輸出與輸入資料 2.5 資料型別轉換 2.6 實例
Java语言程序设计 清华大学出版社 第9章 网络通信.
Signutil.
第14章 Java网络编程 Java语言提供了强大的网络编程功能,能够处理各种网络资源以及进行网络通信。java.net包定义了Java语言网络编程的主要工具类。其中,包括代表网络IP地址的InetAddress类;与URL有关的URL类和URLConnection类;与网络通信有关的Socket类和ServerSocket类。本章包括以下知识点。
Java 第28讲:建立删除文件 主讲教师:李焱 讲师.
JAVA 编 程 技 术 主编 贾振华 2010年1月.
C#程序设计 c# programming 网络编程 C#程序设计课程组.
程式設計實作.
第四章 基本輸出入 Java應用程式的輸出入介面有三種,分別是命令提示字元視窗、AWT元件、及Swing元件。本單元先介紹命令提示字元視窗,AWT請看第16、17章,Swing請看第20章。 輸入 輸出.
西南科技大学网络教育系列课程 高级语程序设计(Java) 第十一章 Java 中的网络编程.
2018/12/3 面向对象与多线程综合实验-网络编程 教师:段鹏飞.
2018/12/3 面向对象与多线程综合实验-网络编程 教师:段鹏飞.
Java语言程序设计 第五部分 Java异常处理.
王豐緒 銘傳大學資訊工程學系 問題:JAVA 物件檔輸出入.
辅导课程六.
网络常用常用命令 课件制作人:谢希仁.
Windows网络操作系统管理 ——Windows Server 2008 R2.
Windows网络操作系统管理 ——Windows Server 2008 R2.
Chapter 11:Java网络编程 授课教师:赵小敏 浙江工业大学 软件学院
异常及处理.
4、按钮事件.
用event class 从input的root文件中,由DmpDataBuffer::ReadObject读取数据的问题
4.2通讯服务模块线程之间传递信息 信息工程系 向模军 Tel: QQ:
Java语言程序设计 清华大学出版社 第8章 输入输出流(1).
Web Server 王宏瑾.
5.3 简单的tcp通讯 信息工程系 向模军 Tel: QQ:
SOA – Experiment 2: Query Classification Web Service
C++语言程序设计 C++语言程序设计 第七章 类与对象 第十一组 C++语言程序设计.
EBNF与操作语义 请用扩展的 BNF 描述 javascript语言里语句的结构;并用操作语义的方法描述对应的语义规则
電子郵件簡介.
本节内容 随机读取 视频提供:昆山爱达人信息技术有限公司.
第四章 团队音乐会序幕: 团队协作平台的快速创建
DQMClientDim.cxx及双光子练习
第二章 Java基本语法 讲师:复凡.
实验七 安全FTP服务器实验 2019/4/28.
计算机网络与网页制作 Chapter 07:Dreamweaver CS5入门
宁波市高校慕课联盟课程 与 进行交互 Linux 系统管理.
Select模型 本节内容 视频提供:昆山爱达人信息技术有限公司 视频录制:yang 官网地址:
2019/5/3 JAVA Socket(UDP).
第二章 Java语法基础.
数据报分片.
Chapter 18 使用GRASP的对象设计示例.
第二章 Java基本语法 讲师:复凡.
WSAAsyncSelect 模型 本节内容 视频提供:昆山爱达人信息技术有限公司 视频录制:yang
阻塞式模型 本节内容 视频提供:昆山爱达人信息技术有限公司 视频录制:yang 官网地址:
基于列存储的RDF数据管理 朱敏
C++语言程序设计 C++语言程序设计 第一章 C++语言概述 第十一组 C++语言程序设计.
C++语言程序设计 C++语言程序设计 第九章 类的特殊成员 第十一组 C++语言程序设计.
助教:廖啟盛 JAVA Socket(UDP) 助教:廖啟盛
第2章 Java语言基础.
第十二章 Java网络编程 1.URL编程 2.Socket网络编程 3.Datagram网络编程.
创建、启动和关闭Activity 本讲大纲: 1、创建Activity 2、配置Activity 3、启动和关闭Activity
实验六静态路由.
使用Fragment 本讲大纲: 1、创建Fragment 2、在Activity中添加Fragment
第二章 Java基础语法 北京传智播客教育
Presentation transcript:

网络程序设计 第二章 客户端Socket用法详解

概述 在客户/服务器通信模式中,客户端需要主动创建与服务器连接的Socket(套接字),服务器段收到客户端的连接请求,也会创建与客户连接的Socket。 Socket可以看作是通信连接两端的收发器,服务端和客户端都是通过Socket来收发数据。 注意:这里的Socket是指客户端应用编程的Socket类,而服务器端的是ServerSocket.

本章的内容 1、Socket类介绍,构造方法/成员方法 2、Socket对象选项设置,控制建立与服务器端的连接,以及收发数据的行为。 3、介绍一个SMTP客户程序,它利用Socket连接到SMTP邮件发送服务器,然后请求服务器发送一封邮件。

2.1 构造Socket Socket的构造方法: 1、Socket() 2、Socket(InetAddress address,int port) 3、Socket(InetAddress address,int port, InetAddress localAddr,int localport) 4、 Socket(String host,int port) 5、 Socket(String host,int port, InetAddress localAddr,int localport)

2.1 InetAddress 在这里InetAddress 表示服务器的IP地址。 InetAddress addr = InetAddress.getLocalHost(); //返回代表“172.17.7.250”的IP地址 InetAddress addr = InetAddress.getByName(“172.17.7.250”); //返回域名为www.bnuep.com 的IP地址: 3. InetAddress addr = InetAddress.getByName(“www.bnuep.com”);

2.1 设置服务器地址 在这里除了第一个不带参数的构造方法,其他构造方法都需要在参数中设定服务器的IP地址或主机名,以及端口:第2和第4构造函数

2.1 设置客户端地址 在一个Socket对象中既包含远程服务器的IP地址和端口信息,也包含本机客户端的IP地址和端口信息。默认情况下,客户端IP地址来自于客户程序所在的主机,而其端口则由操作系统随机分配。 Socket类有两个构造方法允许显式设定客户端的IP地址或主机名和端口:3,5

2.1 使用无参构造函数 当客户端Socket构造方法请求与服务器连接时,可能需要等待一段时间,如果希望等待连接的时间,我们使用第一个无参数的构造函数,如下: Socket socket = new Socket(); SocketAddress remoteAddr = new InetSocketAddress(“localhost”,8000); Socket.connect(remoteAddr,60000); 其中connect(SocketAddress endpoint,int timeout)方法负责连接服务器。

2.1 客户连接服务器时可能抛出的异常 public void connect(String host,int port){ SocketAddress remoteAddr=new InetSocketAddress(host,port); Socket socket=null; String result=""; try { long begin=System.currentTimeMillis(); socket = new Socket(); socket.connect(remoteAddr,1000); //超时时间为1秒钟 long end=System.currentTimeMillis(); result=(end-begin)+"ms"; //计算连接所花的时间 }

2.1 客户连接服务器时可能抛出的异常 catch (BindException e) { result="Local address and port can't be binded"; }catch (UnknownHostException e) { result="Unknown Host"; }catch (ConnectException e) {//如果ServerSocket对象设定连接请求队列长度 result="Connection Refused"; }catch (SocketTimeoutException e) { result="TimeOut"; }catch (IOException e) { result="failure"; } finally { try { if(socket!=null)socket.close(); } catch (IOException e) { e.printStackTrace(); } } System.out.println(remoteAddr+" : "+result); }

2.2获取Socket的信息 1、前面提到了,一个Socket对象同时包含了服务器端和客户端的IP地址和端口信息。 如何编程呢?

2.2获取Socket的信息 getInetAddress(); getPort(); getLocalAddress(); getLocalPort(); getInputStream();可以使用shutdownInput()关闭输入流 getOutputStream();可以使用shutdownOutput()关闭输出流

2.2HTTPClient展示输入输出流 public class HTTPClient { String host="localhost"; int port=6888; Socket socket; public void createSocket()throws Exception{ socket=new Socket("localhost",6888); }

2.2HTTPClient展示输入输出流 public void communicate()throws Exception{ StringBuffer sb=new StringBuffer("GET "+"/crm/About.jsp"+" HTTP/1.1\r\n"); sb.append("Host: www.zh-hr.com\r\n"); sb.append("Accept: */*\r\n"); sb.append("Accept-Language: zh-cn\r\n"); sb.append("Accept-Encoding: gzip, deflate\r\n"); sb.append("User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)\r\n"); sb.append("Connection: Keep-Alive\r\n\r\n"); //发出HTTP请求 OutputStream socketOut=socket.getOutputStream(); socketOut.write(sb.toString().getBytes()); socket.shutdownOutput(); //关闭输出流

2.2HTTPClient展示输入输出流 //接收响应结果 InputStream socketIn=socket.getInputStream(); BufferedReader br = new BufferedReader(new InputStreamReader(socketIn)); String Data ; while ((Data=br.readLine())!=null) System.out.println(Data); socket.close(); }

2.2HTTPClient展示输入输出流 getInetAddress(); getPort(); getLocalAddress(); getLocalPort(); getInputStream(); getOutputStream();

2.3关闭Socket 当客户端与服务端通信结束,应该及时关闭Socket,以释放Socket占用的包括端口在内的各种资源。 Socket的close()方法负责关闭Socket,当Socket对象被关闭,就不能对其输入输出流进行操作,否则会导致IOException 参考前面编程的方式关闭Socket

2.3测试Socket的连接状态 Socket类提供3个状态测试方法: 1、isClosed():如果Socket已经连接到远程主机,但调用了close(),则返回true,否则为false. 2、isConnected():如果Socket曾经连接到远程主机,则返回true,否则false. 3、isBound():如果Socket已经与一个本地端口绑定,则返回true,否则false. 4、如要判断一个Socket对象当前是否处于连接状态,可以如下: Boolean isConnected = socket.isConnected() && !socket.isClosed();

2.4半关闭Socket 进程A与进程B通过Socket通信,假定进程A输出数据,进程B读入数据,进程A如何告知进程B所有数据输出完毕了呢? 有以下四种方法:

2.4半关闭Socket 1、进程A与进程B交换的是字符流,并且都一行一行的读/写数据时,可以事先约定以一个特殊的标志为结束标志,如第一章例子。 2、进程A先发送消息告知进程B所发送的正文的长度,然后再发送正文,进程B只读进相应长度的字符或字节即可。 3、进程A发完所有数据后,关闭Socket。这时进程B读完这些数据后,再执行输入流的read()方法时,该方法返回-1。如果使用BufferdReader的readLine(),则返回null。如下:

2.4半关闭Socket ByteArrayOutputStream buffer=new ByteArrayOutputStream(); byte[] buff=new byte[1024]; int len=-1; while((len=socketIn.read(buff))!=-1){ buffer.write(buff,0,len); }

2.4半关闭Socket BufferedReader br = new BufferedReader(new InputStreamReader(socketIn)); String Data ; while ((Data=br.readLine())!=null) System.out.println(Data);

2.4半关闭Socket 4、当调用Socket的close()方法关闭Socket时,它的输入输出流也都会被关闭。但有时可能仅希望关闭其中之一,可以采用Socket类提供的半关闭方法: shutdownInput():关闭输入流。 shutdownOutput():关闭输出流。 案例HTTPClient采用了半关闭方式

2.4半关闭Socket Socket类提供了输入输出流的状态测试方法: isInputShutDown() isOutputShutDown() 测试:当客户与服务器通信时:如果有一方突然结束程序,或者关闭了Socket,或者单独关闭了输入流或输出流,对另一方会造成什么影响呢?请通过书中实验来理解。

2.5设置Socket选项 对Socket网络通信行为的控制可以通过通过以下选项进行设置: 1、TCP_NODELAY:表示立即发送数据。 2、SO_REUSEADDR:表示是否允许重用Socket所绑定的本地地址。 3、SO_TIMEOUT:表示接收数据时的等待超时时间 4、SO_LINGER:表示当执行Socket的close()方法时,是否立即关闭底层的Socket。 5、SO_SNDBUF:表示发送数据的缓冲区的大小

2.5设置Socket选项 对Socket网络通信行为的控制可以通过通过以下选项进行设置: 6、SO_RCVBUF:表示接收数据的缓冲区的大小。 7、SO_KEEPALIVE:表示对于长时间处于空闲状态的Socket,是否要自动把它关闭。 8、OOBINLINE:表示是否支持发送一个字节的TCP紧急数据。

2.5设置Socket选项 对Socket网络通信行为的控制可以通过以下选项进行设置: 1、TCP_NODELAY:表示立即发送数据。 设置方法:setTcpNoDelay(boolean on) 读取方法:boolean getTcpNoDelay() false适用情形:大批量数据发送,如文件数据 True适用情形:实时传输,如网络游戏

2.5设置Socket选项 2、SO_REUSEADDR:表示是否允许重用Socket所绑定的本地地址。 设置方法:setReuseAddress(boolean on) 读取方法:boolean getReuseAddress() 为了确保一个进程关闭Socket后,即使它还没有释放端口(需要确保接收完延迟数据,确保这些数据不被其他绑定到该端口的新进程接收到),同一主机的其他进程还可以立即重用该端口,可以在Socket没有绑定本地端口调用之前调用setReuseAddress(true),然后才调用connect(remoteAddr)。

2.5设置Socket选项 3、SO_TIMEOUT:表示接收数据时的等待超时时间 设置方法:setSoTimeout(int milliseconds) 读取方法:int getSoTimeout() 在Socket接收数据前调用setSoTimeout(1000),用于设定接收数据的等待超时时间,单位为毫秒,其默认值为0,表示永不超时。 注意实验时,我们设置客户端的SO_TIMEOUT,而不是服务器端的(书中为服务器端)。

2.5设置Socket选项 4、SO_LINGER:表示当执行Socket的close()方法时,是否立即关闭底层的Socket。默认会延迟直到发送完所有剩余的数据,才会真正关闭Socket,断开连接。 设置方法:setSoLinger(boolean on,int seconds) 读取方法:int getSoLinger() 执行socket.setSoLinger(true,0):底层Socket立即关闭,剩余数据丢弃。 执行socket.setSoLinger(true,3600):底层Socket已经发送完剩余数据,或者阻塞超过3600秒,才关闭和丢弃剩余数据。

2.5设置Socket选项 6、SO_RCVBUF:表示接收数据的缓冲区的大小。 一般说来,传输大的连续的数据块(基于http/ftp协议通信)可以使用较大缓冲区,这样减少数据传输的次数,提高传输效率 而对于交互频繁且单次传输数据量比较小的通信方式(telnet/网络游戏),则应采取较小的缓冲区,确保小批量的数据能及时发送给对方。

2.5设置Socket选项 5、SO_SNDBUF:表示发送数据的缓冲区的大小 设置方法:setSendBufferSize(int size) 读取方法:int getSendBufferSize () Receive的设置: 设置方法:setReceiveBufferSize(int size) 读取方法:int getReceiveBufferSize () 类似SO_RCVBUF

2.5设置Socket选项 7、SO_KEEPALIVE:表示对于长时间处于空闲状态的Socket,是否要自动把它关闭。 当此项为True时,表示底层的TCP实现会监视该连接是否有效,当连接处于空闲状态超过了两小时,本地的tcp实现会发送一个数据包给远程的socket。如果远程socket没有发回响应,tcp实现就会持续尝试11分钟,直到收到响应为止。如果未收到响应,tcp实现就会自动关闭本地Socket,断开连接。 在不同网络平台,时限可能不同。 而当其为false时,表示Tcp实现不会监视连接是否有效,不活动的客户段可能会永久存在,而不会注意到服务器已经崩溃

2.5设置Socket选项 8、OOBINLINE:表示是否支持发送一个字节的TCP紧急数据。其默认值为false,这时接收方对紧急数据不做任何处理,直接丢弃。 该项为true时,表示支持发送一个字节的TCP紧急数据,socket.setOOBInline(true)。 Socket类的sendUrgentData(int data)方法用于发送一个字节的TCP紧急数据。

2.5设置Socket选项 9、服务类型选项:在internet上传输数据分为不同的服务类型,它们有不同的定价,类比邮局提供的不同服务—普通信、挂号信、快件,区分速度和可靠性。 用户可以选择不同服务类型:例如发送视频,需要高带宽快速送达目的地,发送电子邮件可以使用低带宽慢速到达目的地。

2.5设置Socket选项 9、服务类型选项: IP规定4种服务类型,用来定性的描述服务的质量。 1、低成本:发送成本低。 2、高可靠性:保证把数据可靠的送达目的地。 3、最高吞吐量:一次可以接收或发送大批量的数据。 4、最小延迟:传输数据的速度快,把数据快速送达目的地。

2.5设置Socket选项 9、服务类型选项:这4种服务类型还可以进行组合。例如:可以同时要求获得高可靠性和最小延迟。Socket类中对应的方法如下: 设置方法:setTrafficClass(int trafficClass) 读取方法:int getTrafficClass() Socket类用4个16进制整数表示服务类型。 低成本:0x02(0000,0010) 高可靠性:0x04(0000,0100) 最高吞吐量:0x08(0000,1000) 最小延迟:0x10(0001,0000)

2.5设置Socket选项 9、服务类型选项:这4种服务类型还可以进行组合。例如:可以同时要求获得高可靠性和最小延迟。对应的设置方法如下: Socket.setTrafficClass(0x04|0x10) 高可靠性设置: Socket.setTrafficClass(0x04)

2.5设置Socket选项 10、设定连接时间、延迟和带宽的相对重要性:在jdk1.5中,socket类提供了一个方法: setPerformancePreferences(int connectionTime,int latency,int bandwidth) 上述方法的3个参数表示网络传输数据的3项指标:最小时间建立连接、最小延迟、最高带宽。

2.5设置Socket选项 10、设定连接时间、延迟和带宽的相对重要性: 在Internet上,数据传输之前先被分割成包。当数据包到达目的地,接收方再以正确的次序把数据包重新装配起来。所谓延迟就是一个数据包到达目的地需要的时间;另外,当你发出对某个目标的请求,目标系统在应答时返回一些数据包,延迟这一概念也可用来描述这一过程所需要的时间。最理想的组合当然是高带宽、低延迟:数据包能够以最快的速度到达,且有充裕的带宽支持;反之,低带宽、高延迟则属于最差的组合。

2.5设置Socket选项 10、设定连接时间、延迟和带宽的相对重要性:   许多通过卫星建立的连接会出现高带宽、高延迟的情形,例如,虽然带宽高达768Kbps,如果你点击网页上的链接或发送一个命令,收到应答数据可能需要一秒以上。由于延迟时间太长,对于许多联机游戏来说,基于卫星的连接几乎无法使用,因为联机游戏要求延迟时间小于半秒或更少。当然,也有的应用对延迟时间的要求不高,例如email。   网络延迟与许多因素有关,最重要的是发送方和接收方之间的路由器,它们对连接的质量有着重要的影响。卫星连接之所以比光缆连接慢,就是因为数据必须通过轨道上的卫星中转。Cable和DSL线路的延迟一般要小得多,但最终还是要由线路的具体情况决定。

2.6发送邮件的SMTP客户程序 STMP协议:建立在TCP/IP协议之上。 规定了把邮件从发送方传输到接收方的规则 STMP客户程序请求发送邮件,STMP服务器负责把邮件传输到目的地。

2.6发送邮件的SMTP客户程序 SMTP设计基于以下通信模型:针对用户的邮件请求,发送SMTP建立与接收SMTP之间建立一个双向传送通道。接收SMTP可以是最终接收者也可以是中间传送者。SMTP命令由发送SMTP发出,由接收SMTP接收,而应答则反方面传送。

2.6发送邮件的SMTP客户程序 一旦传送通道建立,SMTP发送者发送MAIL命令指明邮件发送者。如果SMTP接收者可以接收邮件则返回OK应答。SMTP发送者再发出RCPT命令确认邮件是否接收到。如果SMTP接收者接收,则返回OK应答;如果不能接收到,则发出拒绝接收应答(但不中止整个邮件操作),双方将如此重复多次。当接收者收到全部邮件后会接收到特别的序列,如果接收者成功处理了邮件,则返回OK应答。

2.6发送邮件的SMTP客户程序

2.6发送邮件的SMTP客户程序 class Message{ //表示邮件 String from; //发送者的邮件地址 String to; //接收者的邮件地址 String subject; //邮件标题 String content; //邮件正文 String data; //邮件内容,包括邮件标题和正文 public Message(String from,String to, String subject, String content){ this.from=from; this.to=to; this.subject=subject; this.content=content; data="Subject:"+subject+"\r\n"+content; }

2.6发送邮件的SMTP客户程序 import java.net.*; import java.io.*; public class MailSender{ private String smtpServer="smtp.mydomain.com"; //SMTP邮件服务器的主机名 //private String smtpServer="localhost"; private int port=25; public static void main(String[] args){ Message msg=new Message( "tom@abc.com", //发送者的邮件地址 "linda@def.com", //接收者的邮件地址 "hello", //邮件标题 "hi,I miss you very much."); //邮件正文 new MailSender().sendMail(msg); }

2.6发送邮件的SMTP客户程序 public void sendMail(Message msg){ Socket socket=null; try{ socket = new Socket(smtpServer,port); //连接到邮件服务器 BufferedReader br =getReader(socket); PrintWriter pw = getWriter(socket); String localhost= InetAddress.getLocalHost().getHostName(); //客户主机的名字 sendAndReceive(null,br,pw); //仅仅是为了接收服务器的响应数据 sendAndReceive("HELO " + localhost,br,pw); sendAndReceive("MAIL FROM: <" + msg.from+">",br,pw); sendAndReceive("RCPT TO: <" + msg.to+">",br,pw); sendAndReceive("DATA",br,pw); //接下来开始发送邮件内容 pw.println(msg.data); //发送邮件内容 System.out.println("Client>"+msg.data); sendAndReceive(".",br,pw); //邮件发送完毕 sendAndReceive("QUIT",br,pw); //结束通信 }catch (IOException e){ e.printStackTrace(); }finally{ try{if(socket!=null)socket.close(); }catch (IOException e) {e.printStackTrace();} } }

2.6发送邮件的SMTP客户程序 /** 发送一行字符串,并接收一行服务器的响应数据*/ private void sendAndReceive(String str,BufferedReader br,PrintWriter pw) throws IOException{ if (str != null){ System.out.println("Client>"+str); pw.println(str); //发送完str字符串后,还会发送“\r\n”。 } String response; if ((response = br.readLine()) != null) System.out.println("Server>"+response); private PrintWriter getWriter(Socket socket)throws IOException{ OutputStream socketOut = socket.getOutputStream(); return new PrintWriter(socketOut,true); private BufferedReader getReader(Socket socket)throws IOException{ InputStream socketIn = socket.getInputStream(); return new BufferedReader(new InputStreamReader(socketIn));

2.7Socket小结 1、Socket建立在TCP/IP协议基础上,客户端与服务器都通过Socket来收发数据,也就是说两者都需要创建Socket对象来输入和输出流。 2、构造函数 3、正确关闭Socket 4、Socket属性选项设置,用来控制建立连接、接收和发送数据,以及关闭Socket的行为。