第13章 网络编程

  1 /*****************
  2 ***第13章 网络编程
  3 *******知识点:
  4 **************1.基本概念
  5 ******************1.1 网络OSI模型
  6 ******************1.2 IP地址
  7 ******************1.3 端口地址
  8 ******************1.4 通讯协议
  9 **************2.Java网络相关类
 10 ******************2.1 URLDecoder类
 11 ******************2.2 URLEncoder类
 12 ******************2.3 URL类
 13 ******************2.4 URLConnection 类
 14 ******************2.4 Socket类
 15 ******************2.5 ServerSocket类
 16 ******************2.6 InetAddress类
 17 ******************2.7 InetSocketAddress类
 18 ******************2.8 DatagramSocket类
 19 ******************2.9 DatagramPacket类
 20 ******************2.10 MulticastSocket类
 21 ******************2.11 ProxySelector类
 22 **************3.UDP通信编程
 23 ******************3.1 UDP基本使用
 24 ******************3.2 使用DatagramSocket发送、接收数据
 25 ******************3.3 使用MulticastSocket实现多点广播
 26 **************4.TCP通信编程
 27 ******************4.1 服务器和客户端
 28 ******************4.2 TCP基本使用
 29 ******************4.3 使用NIO实现非阻塞Socket通信
 30 **************5.代理服务器
 31 ******************8.1 直接使用Proxy创建连接
 32 ******************8.2 使用ProxySelector选择代理服务器
 33 **************6.常见网络编程异常
 34 */
 35 
 36 public class test13{
 37     public static void main(String[] args){
 38         demoBaseInfo();//1.基本概念
 39         demoRelatedClass();//2.Java网络相关类
 40         demoUDP();//3.UDP通信编程
 41         demoTCP();//4.TCP通信编程
 42         demoProxyServer();//5.代理服务器
 43         demoCommonException();//6.常见网络编程异常
 44     }
 45     
 46     /*
 47     *1.基本概念
 48     */
 49     public static void demoBaseInfo(){
 50         /**1.1 网络OSI模型**/
 51         //网络OSI模型:OSI(Open System Interconnect),即开放式系统互联。是ISO(国际标准化组织)组织在1985年研究的网络互联模型
 52         //该体系定义了网络互连的七层结构,分别为(从底层到顶层):
 53         //    1.物理层————物理层是OSI参考模型的最低层,它利用传输介质为数据链路层提供物理连接
 54         //    2.数据链路层————数据链路层是为网络层提供服务的,解决两个相邻结点之间的通信问题,传送的协议数据单元称为数据帧
 55         //    3.网络层——————网络层是为传输层提供服务的,传送的协议数据单元称为数据包或分组
 56         //    4.传输层——————传输层的作用是为上层协议提供端到端的可靠和透明的数据传输服务,包括处理差错控制和流量控制等问题
 57         //    5.会话层——————会话层主要功能是管理和协调不同主机上各种进程之间的通信(对话),即负责建立、管理和终止应用程序之间的会话
 58         //    6.表示层——————表示层处理流经结点的数据编码的表示方式问题,以保证一个系统应用层发出的信息可被另一系统的应用层读出
 59         //    7.应用层——————应用层是OSI参考模型的最高层,是用户与网络的接口
 60         
 61         //更多资料参考百度百科或者计算机网络相关书籍  这里就不再详细介绍了
 62         
 63         /**1.2 IP地址**/
 64         //IP————(IP)是Internet Protocol的外语缩写,全称为网络之间互连的协议
 65         //其中Ip地址分为五类,分别是:
 66         //    1.A类地址————范围:1.0.0.0---126.0.0.0
 67         //    2.B类地址————范围:128.0.0.0---191.255.0.0
 68         //    3.C类地址————范围:192.0.0.0---223.255.255.0
 69         //    4.D类地址————范围:224.0.0.0---239.255.255.255
 70         //    5.E类地址————范围:240.0.0.0---255.255.255.254
 71         
 72         //IPv6————"Internet Protocol Version 6"的缩写,也被称作下一代互联网协议,用来替代现行的IPv4(现行的IP)协议的一种新的IP协议
 73         //更多资料参考百度百科或者计算机网络相关书籍  这里就不再详细介绍了
 74         
 75         /**1.3 端口号**/
 76         //端口号————用于区分服务的端口,如TCP/IP协议中的服务端口,端口号的范围从0到65535
 77         //其中端口号分为有:
 78         //    1.公认端口————知名端口即众所周知的端口号,范围从0到1023,这些端口号一般固定分配给一些服务 如:21端口分配给FTP(文件传输协议)服务,25端口分配给SMTP(简单邮件传输协议)服务,
 79         //                                                                                                80端口分配给HTTP服务,135端口分配给RPC(远程过程调用)服务等等
 80         //    2.注册端口————端口号从1025到49151。它们松散地绑定于一些服务
 81         //    3.动态/私有端口————动态端口的范围从1024到65535,这些端口号一般不固定分配给某个服务,也就是说许多服务都可以使用这些端口
 82         //更多资料参考百度百科或者计算机网络相关书籍  这里就不再详细介绍了
 83         
 84         /**1.4 通讯协议**/
 85         //通讯协议——————通信协议又称通信规程,是指通信双方对数据传送控制的一种约定。约定中包括对数据格式,同步方式,传送速度,传送步骤,
       //检纠错方式以及控制字符定义等问题做出统一规定,通信双方必须共同遵守,它也叫做链路控制规程(不要怪我,百科出来滴)
86 //常用的协议有: 87 // 1.TCp————TCP(Transmission Control Protocol 传输控制协议)是一种面向连接的、可靠的、基于字节流的传输层通信协议 88 // 会有三次握手。即A->B(发送请求) B->A(回复A) A->B(发送数据) 89 // 2.UDP————UDP (User Datagram Protocol 用户数据报协议)是一种无连接、效率高的传输层通信协议 90 91 //更多资料参考百度百科或者计算机网络相关书籍 这里就不再详细介绍了 92 } 93 94 /* 95 *2.Java网络相关类 96 */ 97 public static void demoRelatedClass(){ 98 /**2.1 URLDecoder类**/ 99 //URLDecoder类————HTML 格式编码的实用工具类。该类包含了将 String 转换为 application/x-www-form-urlencoded MIME 格式的静态方法 100 //常用方法有:static String encode(String s, String enc) 参数s是要转换的字符串 参数enc是所支持的字符编码名称 101 102 /**2.2 URLEncoder类**/ 103 //URLEncoder类————HTML 格式编码的实用工具类。该类包含了将 String 转换为 application/x-www-form-urlencoded MIME 格式的静态方法 104 //常用方法有:static String encode(String s, String enc) 参数s是要转换的字符串 参数enc是所支持的字符编码名称 105 //用于取代URLDecoder类 106 107 /**2.3 URL类**/ 108 //URL类——————统一资源定位符类,它是指向互联网“资源”的指针 109 //URL url = new URL("http://www.ecnu.edu.cn"); 110 111 /**2.4 URLConnection类**/ 112 //URLConnection类——————抽象类 URLConnection 是所有网络链接类的超类,它代表应用程序和 URL 之间的通信链接 113 //URLConnection uc = url.openConnection(); 114 115 116 /* //演示URL类和URLConnection类 获取网页内容 117 public static void demoURLAndURLEncoder() throws Exception{ 118 URL url = new URL("http://www.baidu.com"); 119 System.out.println("返回主机名:" + url.getHost());//获取主机名 120 System.out.println("返回端口号:" + url.getPort());//获取端口号 121 System.out.println("返回协议名称:" + url.getProtocol());//获取协议 122 123 URLConnection uc = url.openConnection();//打开连接 124 InputStream in = uc.getInputStream();//得到网页输入流 125 126 String directory = "F:\\ciade\\学习\\学习笔记\\Java\\第13章(网络编程)"; //设定为当前路径 127 FileOutputStream out = new FileOutputStream( 128 new File(directory + "\\testdemoURLAndURLEncoder.html") 129 ); 130 int c; 131 while((c = in.read()) != -1){ 132 out.write(c);//写入本地文件中 133 } 134 in.close(); 135 out.close(); 136 } 137 */ 138 139 /**2.4 Socket类**/ 140 //Socket类:此类实现客户端套接字(也可以就叫“套接字”)。套接字是两台机器间通信的端点。TCP可用 141 /* 142 import java.util.*; 143 import java.io.*; 144 import java.net.*; 145 146 class Receive implements Runnable{ 147 private Socket s; 148 public Receive(Socket s){ 149 this.s = s; 150 } 151 public void run() { 152 try{ 153 Scanner in = new Scanner(s.getInputStream());//接受数据 154 String str=null; 155 while(true){ 156 str = in.nextLine(); 157 System.out.println("客户端传来:" + str); 158 } 159 }catch(Exception e){ 160 161 } 162 } 163 } 164 public class Client{ 165 public static void main(String[] args) throws Exception{ 166 Socket s = new Socket("localhost",8819); 167 PrintWriter out = new PrintWriter(s.getOutputStream(),true); 168 Thread t = new Thread(new Receive(s)); 169 t.start(); 170 //以下代码用于发送数据 171 Scanner in = new Scanner(System.in);//键盘输入 172 while(in.hasNextLine()){ //一直不断 173 out.println(in.nextLine()); //发送键盘输入数据 174 } 175 } 176 177 } 178 */ 179 //配合服务器端一同执行 180 181 /**2.5 ServerSocket类**/ 182 //ServerSocket类:此类实现服务器套接字 .TCP 可用 183 /* 184 import java.util.*; 185 import java.io.*; 186 import java.net.*; 187 public class Server{ 188 public static void main(String[]args)throws Exception{ 189 ServerSocket server = new ServerSocket(8819); 190 Socket s = server.accept(); 191 PrintWriter out = new PrintWriter(s.getOutputStream(),true); 192 Thread t = new Thread(new Receive1(s)); 193 t.start(); 194 //以下代码用于发送数据 195 Scanner in = new Scanner(System.in);//键盘输入 196 while(in.hasNextLine()){ //一直不断 197 out.println(in.nextLine()); //发送键盘输入数据 198 } 199 } 200 } 201 class Receive1 implements Runnable //这个类用于接收数据 202 { 203 private Socket s; 204 public Receive1(Socket s) 205 { 206 this.s = s; 207 } 208 public void run() 209 { 210 try{ 211 Scanner in = new Scanner(s.getInputStream()); //in:接收数据 212 213 String str = null; 214 while(true) 215 { 216 str = in.nextLine(); 217 System.out.println("客户端说:"+str); //打印接收数据 218 } 219 220 } 221 catch(Exception e){} 222 } 223 } 224 */ 225 //配合客户端一同执行 226 227 /**2.6 InetAddress类**/ 228 //InetAddress类:此类表示 Internet Protocol version 4 (IPv4) 地址(不包含端口号) 229 230 /**2.7 InetSocketAddress类**/ 231 //InetSocketAddress类:此类实现 IP 套接字地址(IP 地址 + 端口号) 232 233 /* //演示InetAddress、InetSocketAddress 234 public static void demoInetAddressAndInetSocketAddress() throws Exception { 235 InetAddress local = InetAddress.getLocalHost(); 236 System.out.println("返回本机地址:" + local.getHostAddress());//获取本地地址 237 System.out.println("返回本机名:" + local.getHostName());//获取主机名 238 239 InetAddress[] remote = InetAddress.getAllByName("www.baidu.com");//如果一个地址多个Ip,则返回IP 地址所组成的数组 240 for(InetAddress a : remote){ 241 System.out.println("地址:" + a.getHostAddress()); 242 System.out.println("名称:" + a.getHostName()); 243 } 244 245 InetSocketAddress isAdd = new InetSocketAddress(local.getHostAddress(),8080);//第一个参数为IP,第二个参数为端口号 246 System.out.println("是否已解析地址:" + isAdd.isUnresolved());//如果无法将主机名解析为 InetAddress,则返回 true。 247 248 System.out.println("地址:" + isAdd.getAddress() + ",端口:" + isAdd.getPort());//获取IP和端口 249 250 251 } 252 */ 253 254 /**2.8 DatagramSocket类**/ 255 //DatagramSocket类:表示用来发送和接收数据报包的套接字。在此类上总是启用 UDP 广播发送 256 257 /**2.9 DatagramPacket类**/ 258 //DatagramPacket类:此类表示数据报包 259 260 /*//演示DatagramSocket、DatagramPacket类 261 //服务器 262 class ServerDemo implements Runnable{ 263 public void run(){ 264 try{ 265 DatagramSocket dgs = new DatagramSocket(8081); 266 while(true){ 267 byte[] buf = new byte[1024]; 268 DatagramPacket dp = new DatagramPacket(buf,buf.length); 269 dgs.receive(dp); 270 String ip = dp.getAddress().getHostAddress(); 271 String data = new String(dp.getData(),0,dp.getLength()); 272 System.out.println("IP:" + ip + "发来消息:" + data); 273 dgs.close(); 274 } 275 }catch(Exception e){ 276 277 } 278 } 279 } 280 281 //客户端 282 class ClientDemo implements Runnable{ 283 public void run(){ 284 try{ 285 DatagramSocket dc = new DatagramSocket(); 286 InetAddress ip = InetAddress.getByName("localhost"); 287 BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 288 String line =null; 289 DatagramPacket dp =null; 290 while((line=br.readLine()) != null){ 291 if("886".equals(line)){ 292 break; 293 } 294 dp = new DatagramPacket(line.getBytes(),line.length(),ip,8081); 295 dc.send(dp); 296 dc.close(); 297 br.close(); 298 } 299 }catch(Exception e){ 300 301 } 302 } 303 } 304 */ 305 306 /**2.10 MulticastSocket类**/ 307 //MulticastSocket类:用于发送和接收 IP 多播包,在此类上总是启用 UDP 广播发送 308 //组播时用到 309 310 /**2.11 ProxySelector类**/ 311 //ProxySelector类:连接到 URL 引用的网络资源时选择要使用的代理服务器类,抽象类 312 } 313 314 /* 315 *3.UDP通信编程 316 */ 317 public static void demoUDP(){ 318 /**3.1 UDP基本使用**/ 319 /**3.2 使用DatagramSocket发送、接收数据**/ 320 //参考上面 演示DatagramSocket、DatagramPacket类中的使用 321 322 /**3.3 使用MulticastSocket实现多点广播**/ 323 //DatagramSocket只允许数据报发送给指定的目标地址, 324 //而MulticastSocket可以将数据报以广播方式发送到数量不等的多个客户端 325 /* 326 MulticastSocket ms =new MulticastSocket(4000); //新建组播socket 327 InetAddress ia = InetAddress.getByName("224.2.2.2");//组播地址 328 ms.joinGroup(ia); //加入主播组 329 byte[] buffer=new byte[512]; 330 //发送数据包 331 byte[] buf = "Hello,This is a member of multicast!".getBytes(); 332 DategramPacket packet = 333 new DatagramPacket(buf, buf.length,ia,4000); 334 ms.send(packet); 335 336 //接收数据包 337 DatagramPacket dp =new DatagramPacket(buffer,buffer.length); 338 ms.receive(dp); 339 String s=new String(dp.getData()).trim(); 340 System.out.println(s); 341 ms.leaveGroup(address); 342 ms.close(); 343 */ 344 } 345 346 /* 347 *4.TCP通信编程 348 */ 349 public static void demoTCP(){ 350 /**4.1 服务器和客户端**/ 351 352 /**4.2 TCP基本使用**/ 353 /* 354 //服务端: 355 //1,建立服务器端的socket服务,serverSocket(); 356 // 并监听一个端口。 357 //2,获取连接过来的客户端对象 358 // 通过ServerSocket的accept方法,没有连接就会等,所以这个方法阻塞 359 // 360 //3,客户端如果发过来数据,那么服务端要使用对应的客户端对象,并获取到该客户端对象的读取流来读取 361 // 发过来的数据,将之打印在控制台上。 362 //4,关闭服务器端。(可选择) 363 // 364 import java.io.*; 365 import java.net.*; 366 367 //代表server类 368 public class TcpChat 369 { 370 public static void main(String[]args)throws Exception 371 { 372 //创建绑定到特定端口的服务器套接字。 373 ServerSocket ss = new ServerSocket(8082); 374 //侦听并接受到此套接字的连接。 375 Socket sk = ss.accept(); 376 377 String ip = sk.getInetAddress().getHostAddress();//得到ip地址 378 //返回此套接字的输入流。 379 InputStream is = sk.getInputStream(); 380 381 int len = 0; 382 byte []buf = new byte[1024]; 383 while((len=is.read(buf))!=-1) 384 { 385 System.out.println(ip+""...""+new String(buf,0,len)); 386 } 387 388 sk.close(); 389 ss.close(); 390 } 391 } 392 393 394 //客户端: 395 //通过查阅socket对象,发现在该对象上建立时,就可以去连接到指定的主机了。 396 //因为tcp是面向连接的,所以在建立socket服务是,就要有服务器端的存在,并连接成功。形成通路后, 397 //在该通道进行数据的传输。 398 // 399 //需求:给服务器端发送一个文本数据。 400 401 //步骤: 402 //1,创建Socket服务,并指定要连接的主机和端口。 403 // 404 405 406 407 //代表客户端类 408 class TcpClient 409 { 410 public static void main(String []arg)throws Exception 411 { 412 //创建一个客户端服务 413 Socket s = new Socket(""192.168.0.101"", 8082); 414 //指定要发送的内容 415 byte[] buf = ""Hello Rory, You do it!"".getBytes(); 416 //得到此套接字的输出流。 417 OutputStream os = s.getOutputStream(); 418 419 os.write(buf); 420 s.close(); 421 422 423 } 424 } 425 */ 426 427 /**4.3 使用NIO实现非阻塞Socket通信**/ 428 /* 429 //服务器端 430 import java.io.IOException; 431 import java.net.InetSocketAddress; 432 import java.nio.ByteBuffer; 433 import java.nio.channels.Channel; 434 import java.nio.channels.SelectionKey; 435 import java.nio.channels.Selector; 436 import java.nio.channels.ServerSocketChannel; 437 import java.nio.channels.SocketChannel; 438 import java.nio.charset.Charset; 439 440 public class NServer { 441 442 // 用于检测所有的Channel状态的selector 443 private Selector selector = null; 444 static final int PORT = 30000; 445 // 定义实现编码、解码的字符串集对象 446 private Charset charse = Charset.forName("GBK"); 447 448 public void init() throws IOException { 449 selector = Selector.open(); 450 // 通过open方法来打开一个未绑定的ServerSocketChannel实例 451 ServerSocketChannel server = ServerSocketChannel.open(); 452 InetSocketAddress isa = new InetSocketAddress("127.0.0.1", PORT); 453 // 将该ServerSocketChannel绑定到指定的IP地址 454 server.bind(isa); 455 // 设置serverSocket已非阻塞方式工作 456 server.configureBlocking(false); 457 // 将server注册到指定的selector对象 458 server.register(selector, SelectionKey.OP_ACCEPT); 459 while (selector.select() > 0) { 460 // 一次处理selector上的每个选择的SelectionKey 461 for (SelectionKey sk : selector.selectedKeys()) { 462 // 从selector上已选择的Kye集中删除正在处理的SelectionKey 463 selector.selectedKeys().remove(sk); 464 // 如果sk对应的Channel包含客户端的连接请求 465 if (sk.isAcceptable()) { 466 // 调用accept方法接收连接,产生服务器段的SocketChennal 467 SocketChannel sc = server.accept(); 468 // 设置采用非阻塞模式 469 sc.configureBlocking(false); 470 // 将该SocketChannel注册到selector 471 sc.register(selector, SelectionKey.OP_READ); 472 } 473 // 如果sk对应的Channel有数据需要读取 474 if (sk.isReadable()) { 475 // 获取该SelectionKey对银行的Channel,该Channel中有刻度的数据 476 SocketChannel sc = (SocketChannel) sk.channel(); 477 // 定义备注执行读取数据源的ByteBuffer 478 ByteBuffer buff = ByteBuffer.allocate(1024); 479 String content = ""; 480 // 开始读取数据 481 try { 482 while (sc.read(buff) > 0) { 483 buff.flip(); 484 content += charse.decode(buff); 485 } 486 System.out.println("读取的数据:" + content); 487 // 将sk对应的Channel设置成准备下一次读取 488 sk.interestOps(SelectionKey.OP_READ); 489 } 490 // 如果捕获到该sk对银行的Channel出现了异常,表明 491 // Channel对应的Client出现了问题,所以从Selector中取消 492 catch (IOException io) { 493 // 从Selector中删除指定的SelectionKey 494 sk.cancel(); 495 if (sk.channel() != null) { 496 sk.channel().close(); 497 } 498 } 499 // 如果content的长度大于0,则连天信息不为空 500 if (content.length() > 0) { 501 // 遍历selector里注册的所有SelectionKey 502 for (SelectionKey key : selector.keys()) { 503 // 获取该key对应的Channel 504 Channel targerChannel = key.channel(); 505 // 如果该Channel是SocketChannel对象 506 if (targerChannel instanceof SocketChannel) { 507 // 将读取到的内容写入该Channel中 508 SocketChannel dest = (SocketChannel) targerChannel; 509 dest.write(charse.encode(content)); 510 } 511 } 512 } 513 } 514 } 515 } 516 517 } 518 519 public static void main(String [] args) throws IOException{ 520 new NServer().init(); 521 } 522 523 } 524 525 526 //客户端 527 import java.io.IOException; 528 import java.net.InetSocketAddress; 529 import java.nio.ByteBuffer; 530 import java.nio.channels.SelectionKey; 531 import java.nio.channels.Selector; 532 import java.nio.channels.SocketChannel; 533 import java.nio.charset.Charset; 534 import java.util.Scanner; 535 536 public class NClient { 537 538 //定义检测Sockethannel的Selector对象 539 private Selector selector=null; 540 static final int PORT=30000; 541 //定义处理编码的字符集 542 private Charset charset=Charset.forName("GBK"); 543 //客户端SocketChannel 544 private SocketChannel sc=null; 545 546 public void init() throws IOException{ 547 selector=Selector.open(); 548 InetSocketAddress isa=new InetSocketAddress("127.0.0.1", PORT); 549 //调用open的静态方法创建连接指定的主机的SocketChannel 550 sc=SocketChannel.open(isa); 551 //设置该sc已非阻塞的方式工作 552 sc.configureBlocking(false); 553 //将SocketChannel对象注册到指定的Selector 554 sc.register(selector, SelectionKey.OP_READ); 555 //启动读取服务器数据端的线程 556 new ClientThread().start(); 557 //创建键盘输入流 558 Scanner scan=new Scanner(System.in); 559 while(scan.hasNextLine()){ 560 //读取键盘的输入 561 String line=scan.nextLine(); 562 //将键盘的内容输出到SocketChanenel中 563 sc.write(charset.encode(line)); 564 } 565 } 566 567 //定义读取服务器端的数据的线程 568 private class ClientThread extends Thread{ 569 570 @Override 571 public void run() { 572 try{ 573 while(selector.select()>0){ 574 //遍历每个有可能的IO操作的Channel对银行的SelectionKey 575 for(SelectionKey sk:selector.selectedKeys()){ 576 //删除正在处理的SelectionKey 577 selector.selectedKeys().remove(sk); 578 //如果该SelectionKey对应的Channel中有可读的数据 579 if(sk.isReadable()){ 580 //使用NIO读取Channel中的数据 581 SocketChannel sc=(SocketChannel)sk.channel(); 582 String content=""; 583 ByteBuffer bff=ByteBuffer.allocate(1024); 584 while(sc.read(bff)>0){ 585 sc.read(bff); 586 bff.flip(); 587 content+=charset.decode(bff); 588 } 589 //打印读取的内容 590 System.out.println("聊天信息:"+content); 591 sk.interestOps(SelectionKey.OP_READ); 592 593 } 594 } 595 } 596 597 }catch(IOException io){ 598 io.printStackTrace(); 599 } 600 } 601 602 } 603 604 public static void main(String [] args) throws IOException{ 605 new NClient().init(); 606 } 607 608 } 609 */ 610 } 611 612 /* 613 *5.代理服务器 614 */ 615 public static void demoProxyServer(){ 616 /**8.1 直接使用Proxy创建连接**/ 617 /* 618 URL url = new URL("127.0.0.1");//创建一个代理服务器对象 619 620 //使用指定的代理服务器打开连接 621 Proxy proxy = new Proxy(Proxy.Type.HTTP,new InetSocketAddress(proxyAddress , proxyPort)); 622 623 URLConnection conn = url.openConnection(proxy);//设置超时时长 624 conn.setConnectTimeout(5000); 625 */ 626 627 /**8.2 使用ProxySelector选择代理服务器**/ 628 /* 629 系统提供了默认的ProxySelector子类作为代理选择器,开发者可以实现自己的代理选择器, 630 程序可以通过继承ProxySelector来实现自己的代理选择器。继承ProxySelector需要重写两个方法: 631 List<Proxy> select(URI uri):实现该方法让代理选择器根据不同的URI来使用不同的代理服务器, 632 该方法就是代理选择器管理网络连接使用代理服务器的关键。 633 connectFailed(URI uri, SocketAddress sa, IOException ioe):当系统通过默认的代理服务器建立连接失败后, 634 代理选择器将会自动调用该方法。通过重写该方法可以对连接代理服务器失败的情形进行处理。 635 636 //更多使用说明详见API文档或者度娘 637 */ 638 } 639 640 /* 641 *6.常见网络编程异常 642 */ 643 public static void demoCommonException(){ 644 //1.java.net.BindException:异常的原因是以为与port一样的一个端口已经被启动,并进行监听 645 //2.java.net.ConnectException:异常发生的原因是或者具有ip地址的机器不能找到(也就是说从当前机器不存在到指定ip路由),或者是该ip存在,但找不到指定的端口进行监听 646 //3.java.net.SocketException: 647 // 3.1异常的原因是己方主动关闭了连接后(调用了Socket的close方法)再对网络连接进行读写操作 648 // 3.2异常的原因是甲方主动关闭了连接后(调用了Socket的close方法)再对网络连接进行读写操作 649 // 3.3简单的说就是在连接断开后的读和写操作引起的 650 //解决方式:首先确保程序退出前关闭所有的网络连接,其次是要检测对方的关闭连接操作,发现对方关闭连接后自己也要关闭该连接 651 } 652 653 654 /**部分文档参考至: http://blog.csdn.net/xiazdong/article/details/6713691 655 http://blog.sina.com.cn/s/blog_4d9c3fec0101tztp.html 656 http://blog.csdn.net/x605940745/article/details/14123343**/ 657 }
原文地址:https://www.cnblogs.com/ciade/p/4773308.html