`
snoopy7713
  • 浏览: 1152841 次
  • 性别: Icon_minigender_2
  • 来自: 火星郊区
博客专栏
Group-logo
OSGi
浏览量:0
社区版块
存档分类
最新评论

网络编程

    博客分类:
  • java
阅读更多

计算机网络基础

什么是计算机网络

把分布在不同地理区域的计算机与专门的外部设备用通信线路互联成一个规模大,功能强的网络系统,从而使众多的计算机可以方便的相互传递信息,共享硬件,软件,数据信息等资源.

计算机网络的主要功能

资源共享

信息传输与集中处理

均衡负荷与分布处理

综合信息服务

计算机网络分类

按规模大小和延伸范围划分:

局域网(LAN-local area network)

城域网(MAN-metropolitan area network)

广域网(WAN-wide area network)

按照网络的拓扑(Topology)结构划分:

环形网,星形网,总线型网等

按照通信,传输的介质来划分:

双绞线网,同轴电缆网,光纤网,卫星网等.

按照信号频带占方式划分:

基带网和宽带网

计算机网络工作模式

专用服务器结构(Server-Based)

又称为"工作站/文件服务器"结构,由若干台微机工作站与一台或多台文件服务器通过通信线路连接起来组成工作站存取服务器文件,共享存储设备.

客户机/服务器模式(Client/Server,C/S)

其中一台或几台较大的计算机集中进行共享数据库的管理和存取,称为服务器,而将其它的应用处理工作分散到网络中其他微机上去做,构成分布式的处理系统.

对等式网络(Peer-to-Peer,P2P)

在拓扑结构上与专用Server与C/S相同,在对等式网络结构中,没有专用服务器,每一个工作站既可以起客户机作用也可以做1服务器作用 .

网络通信协议及接口

什么事网络通信协议

计算机网络中实现通信必须有一些约定即通信协议,对速率,传输代码,代码结构,传输控制步骤,出错控制等制定标准.

网络通信接口

为了使两个结点之间能进行对话,必须在它们之间建立通信工具(即接口),使彼此之间,能进行信息交换,接口包括两部分:

硬件装置:实现结点之间的信息传送

软件装置:规定双方进行通信的约定协议

通信协议分层的思想

为什么要分层

由于结点之间联系很复杂,在制定协议时,把复杂成份分解成一些简单的成份,再将它们复合起来,最常用的复合方式是层次方式,即同层间可以通信,上一层可以调用下一层,而与再下一层不发生关系.

通信协议的分层规定

把用户应用程序作为最高层,把物理通信线路作为最底层,将其间的协议处理分为若干层,规定每层处理的任务,也规定每层的接口标准.

数据的封装与拆封

封装:发送方数据在网络模型的各层传送过程中加入头尾的过程

拆封:接受方收到书记后去除相应的头尾的过程.

常用网络通信协议

TCP/IP协议

TCP(Transmission Control Protocol,传输控制协议)

IP(Internet Protocol,网际协议)

HTTP协议

HTTP(Hypertext Transfeer Protocol,超文本传输协议)

FTP协议

FTP(File Transfer Protocol,文本传输协议)

SMTP协议

SMTP(Simple Mail Transfer Protocol,简单邮件传输协议)

POP3/IMAP协议

pop3(Post office Protoco-version3,邮局协议版本3)

IMAP(Internet Message Access Protocol,Internet消息访问协议)

IP地址/域名/端口

IP地址

Tcp/ip使用ip地址来标识源地址和目的地地址

ip地址格式:192.111.12.43

目前正在普遍使用的ip协议时第4版(Version 4)的称为IPv4,新版本(IPV6)协议已开始推广.

域名(Domain Address)

便于记忆的,字符串形式,如:baidu.com

与ip地址间存在映射关系,由位于网络中的域名服务器(DNS,Domain Name Server)负责将域名解析为相应的ip地址.

端口(Port)

逻辑协议上的数据传输通道,或者说模拟通道,Tcp/ip协议约定,每台计算机拥有65536个这种逻辑通信端口.

端口号:用于标识这些端口的整数编号,其取值范围为0-65535

相关API

JDK的java.net包中定义了与ip地址/域名有关的类

java.net.InetAddress

32位或128位无符号数字表示的ip地址

java.net.Inet4Address

继承了InetAddress类,以32位无符号数字表示的IPv4地址,其典型表示形式是由圆点分隔开的4段,取值范围0-255的十进制数值

java.net.Inet6Address

继承了InetAddress,以128位无符号数字表示的ipv6地址,其典型表示形式是由冒号分隔开的8段,取值范围0000-ffff的十六进制数值,例如"1090:2:2:2:1:311:123C:123A"

 

Java代码  收藏代码
  1. import  java.net.InetAddress;  
  2.   
  3. public   class  TestInetAddress {  
  4.     public   static   void  main( String args[]) {  
  5.         try {  
  6.             InetAddress ia = InetAddress.getLocalHost();  
  7.             showInfo(ia);  
  8.               
  9.             ia = InetAddress.getByName("www.sina.com.cn" );  
  10.             showInfo(ia);  
  11.         }catch (java.net.UnknownHostException e){  
  12.             e.printStackTrace();  
  13.         }  
  14.           
  15.     }  
  16.       
  17.     public   static   void  showInfo(InetAddress ia){  
  18.         String name = ia.getHostName();  
  19.         String address = ia.getHostAddress();  
  20.         System.out.println(name);  
  21.         System.out.println(address);  
  22.         System.out.println("----------------" );  
  23.     }  
  24. }  

URL

URL(Uniform Resource Locator统一资源定位器)用于表示Internet上资源的地址。

URL格式:

<协议名><资源所在主机名>[:<端口号>]<资源名>

例如: http://www.baidu.com/map/index.htm

java.net包定义了对应的URL类常用方法:

public URL(String spec);

public final InputStream openStream() throws IOException

使用URL读取网络资源

Java代码  收藏代码
  1. import  java.io.InputStream;  
  2. import  java.io.InputStreamReader;  
  3. import  java.io.BufferedReader;  
  4. import  java.io.IOException;  
  5. import  java.net.URL;  
  6. import  java.net.MalformedURLException;  
  7. public   class  URLReader{  
  8.     public   static   void  main(String args[]){  
  9.         //System.setProperty("http.proxyHost","192.168.1.1");   
  10.         //System.setProperty("http.proxyPort","11080");   
  11.         try {  
  12.             URL tirc = new  URL( "http://www.google.cn/" );  
  13.             BufferedReader in = new  BufferedReader( new    
  14.                 InputStreamReader(tirc.openStream()));  
  15.             String s;  
  16.             while ((s = in.readLine())!= null )  
  17.                 System.out.println(s);  
  18.             in.close();   
  19.         }catch (MalformedURLException e) {  
  20.             System.out.println(e);    
  21.         }catch (IOException e){  
  22.             System.out.println(e);  
  23.         }     
  24.     }  
  25. }  

Socket编程

  • 两个进程间可以通过一个双向的网络通信连接实现数据交换,这种通信链路的端点被称为"套接字"(Socket)
  • Socket通常用来实现Client-Server连接.
  • 建立连接时所需的寻址信息:1远程计算机的机器名或ip地址;2试图连接的端口号(Port number)

java.net包中定义了两个类Socket和ServerSocket,分别用来实现双向连接的client和server端.

Socket通信模型

Socket编程基本步骤

  1. 建立网络连接
  2. 打开连接到Socket的输入/输出流;
  3. 通过已打开的i/o流进行数据读/写操作;
  4. 关闭已打开的i/o流和Socket

图像用户界面自由聊天程序

Java代码  收藏代码
  1. import  java.io.*;  
  2. import  java.net.*;  
  3. import  java.awt.*;  
  4. import  java.awt.event.*;  
  5. public   class  TestServer {  
  6.     private  ServerSocket ss;  
  7.     private  Socket s;  
  8.     private  DataInputStream dis;  
  9.     private  DataOutputStream dos;  
  10.     private  TextArea ta;  
  11.     private  TextField tf;  
  12.           
  13.     public   static   void  main(String args[]) {  
  14.         TestServer ts = new  TestServer();  
  15.         ts.createUI();  
  16.         ts.connect();     
  17.         ts.createThread();  
  18.     }  
  19.     public   void  connect(){  
  20.         try  {         
  21.             ss = new  ServerSocket( 8888 );  
  22.             s = ss.accept();  
  23.             dis = new  DataInputStream(s.getInputStream());  
  24.             dos = new  DataOutputStream(s.getOutputStream());  
  25.         }catch  (IOException e) {  
  26.             e.printStackTrace();      
  27.             //13701303436     
  28.                   
  29.         }  
  30.     }  
  31.       
  32.     public   void  createUI(){  
  33.         Frame f = new  Frame( "Server" );  
  34.         ta = new  TextArea();  
  35.         tf = new  TextField();  
  36.         Button send = new  Button( "发送" );  
  37.         Panel p = new  Panel();  
  38.         p.setLayout(new  BorderLayout());  
  39.         p.add(tf,"Center" );  
  40.         p.add(send,"East" );  
  41.         f.add(ta,"Center" );  
  42.         f.add(p,"South" );  
  43.         MyServerListener listener = new  MyServerListener( this );  
  44.         send.addActionListener(listener);         
  45.         tf.addActionListener(listener);  
  46.         f.addWindowListener(new  WindowAdapter(){  
  47.             public   void  windowClosing(WindowEvent e){  
  48.                 System.exit(0 );   
  49.             }     
  50.         });  
  51.         f.setSize(400 , 400 );  
  52.         f.setVisible(true );   
  53.     }  
  54.   
  55.     public   void  createThread(){  
  56.         MyServerReader reader = new  MyServerReader( this );  
  57.         reader.start();   
  58.     }  
  59.       
  60.     public   void  close(){  
  61.         try {  
  62.             dis.close();  
  63.             dos.close();  
  64.             s.close();  
  65.             ss.close();   
  66.         }catch  (IOException e) {  
  67.             e.printStackTrace();          
  68.         }  
  69.     }  
  70.   
  71.     public  DataInputStream getDataInputStream(){  
  72.         return  dis;   
  73.     }  
  74.     public  DataOutputStream getDataOutputStream(){  
  75.         return  dos;   
  76.     }  
  77.     public  TextArea getTextArea(){  
  78.         return  ta;    
  79.     }  
  80.     public  TextField getTextField(){  
  81.         return  tf;    
  82.     }  
  83. }  
  84.   
  85. class  MyServerListener  implements  ActionListener{  
  86.     private  TestServer server;    
  87.     public  MyServerListener(TestServer server){  
  88.         this .server = server;  
  89.     }  
  90.     public   void  actionPerformed(ActionEvent e){  
  91.         TextField tf = server.getTextField();  
  92.         String info = tf.getText();  
  93.         server.getTextArea().append("自己说: "  + info +  "\n" );  
  94.         try {  
  95.             server.getDataOutputStream().writeUTF(info);      
  96.         }catch  (IOException e1) {  
  97.             e1.printStackTrace();         
  98.         }  
  99.         if (info.equals( "bye" )){  
  100.             server.close();  
  101.             System.exit(0 );   
  102.         }  
  103.         tf.setText("" );  
  104.         tf.requestFocus();  
  105.     }     
  106. }  
  107.   
  108. class  MyServerReader  extends  Thread{  
  109.     private  TestServer server;  
  110.     public  MyServerReader(TestServer server){  
  111.         this .server = server;     
  112.     }  
  113.     public   void  run(){  
  114.         String info;  
  115.         DataInputStream dis = server.getDataInputStream();  
  116.         TextArea ta = server.getTextArea();  
  117.         try {  
  118.             while ( true ){  
  119.                 info = dis.readUTF();  
  120.                 ta.append("对方说: "  + info +  "\n" );  
  121.                 if (info.equals( "bye" )){  
  122.                     server.close();  
  123.                     System.exit(0 );  
  124.                 }  
  125.             }         
  126.         }catch  (IOException e) {  
  127.             e.printStackTrace();          
  128.         }     
  129.     }     
  130. }  

 

Java代码  收藏代码
  1. import  java.io.*;  
  2. import  java.net.*;  
  3. import  java.awt.*;  
  4. import  java.awt.event.*;  
  5. public   class  TestClient {  
  6.     private  Socket s;  
  7.     private  DataInputStream dis;  
  8.     private  DataOutputStream dos;  
  9.     private  TextArea ta;  
  10.     private  TextField tf;  
  11.           
  12.     public   static   void  main(String args[]) {  
  13.         TestClient tc = new  TestClient();  
  14.         tc.createUI();  
  15.         tc.connect();     
  16.         tc.createThread();  
  17.     }  
  18.     public   void  connect(){  
  19.         try  {         
  20.             s = new  Socket( "127.0.0.1" , 8888 );  
  21.             dos = new  DataOutputStream(s.getOutputStream());  
  22.             dis = new  DataInputStream(s.getInputStream());  
  23.         }catch  (IOException e) {  
  24.             e.printStackTrace();          
  25.         }  
  26.     }  
  27.       
  28.     public   void  createUI(){  
  29.         Frame f = new  Frame( "Client" );  
  30.         ta = new  TextArea();  
  31.         tf = new  TextField();  
  32.         Button send = new  Button( "发送" );  
  33.         Panel p = new  Panel();  
  34.         p.setLayout(new  BorderLayout());  
  35.         p.add(tf,"Center" );  
  36.         p.add(send,"East" );  
  37.         f.add(ta,"Center" );  
  38.         f.add(p,"South" );  
  39.         MyClientListener listener = new  MyClientListener( this );  
  40.         send.addActionListener(listener);  
  41.         tf.addActionListener(listener);  
  42.         f.addWindowListener(new  WindowAdapter(){  
  43.             public   void  windowClosing(WindowEvent e){  
  44.                 System.exit(0 );   
  45.             }     
  46.         });  
  47.         f.setSize(400 , 400 );  
  48.         f.setLocation(600 , 0 );  
  49.         f.setVisible(true );   
  50.     }  
  51.       
  52.     public   void  createThread(){  
  53.         MyClientReader reader = new  MyClientReader( this );  
  54.         reader.start();   
  55.     }  
  56.       
  57.     public   void  close(){  
  58.         try {  
  59.             dis.close();  
  60.             dos.close();  
  61.             s.close();  
  62.         }catch  (IOException e) {  
  63.             e.printStackTrace();          
  64.         }  
  65.     }  
  66.   
  67.     public  DataInputStream getDataInputStream(){  
  68.         return  dis;   
  69.     }  
  70.     public  DataOutputStream getDataOutputStream(){  
  71.         return  dos;   
  72.     }  
  73.     public  TextArea getTextArea(){  
  74.         return  ta;    
  75.     }  
  76.     public  TextField getTextField(){  
  77.         return  tf;    
  78.     }  
  79. }  
  80.   
  81. class  MyClientListener  implements  ActionListener{  
  82.       
  83.     private  TestClient client;    
  84.     public  MyClientListener(TestClient client){  
  85.         this .client = client;  
  86.     }  
  87.     public   void  actionPerformed(ActionEvent e){  
  88.         TextField tf = client.getTextField();  
  89.         String info = tf.getText();  
  90.         client.getTextArea().append("自己说: "  + info +  "\n" );  
  91.         try {  
  92.             client.getDataOutputStream().writeUTF(info);      
  93.         }catch  (IOException e1) {  
  94.             e1.printStackTrace();         
  95.         }  
  96.         if (info.equals( "bye" )){  
  97.             client.close();  
  98.             System.exit(0 );   
  99.         }  
  100.         tf.setText("" );  
  101.         tf.requestFocus();        
  102.     }     
  103. }  
  104.   
  105. class  MyClientReader  extends  Thread{  
  106.     private  TestClient client;  
  107.     public  MyClientReader(TestClient client){  
  108.         this .client = client;     
  109.     }  
  110.     public   void  run(){  
  111.         String info;  
  112.         DataInputStream dis = client.getDataInputStream();  
  113.         TextArea ta = client.getTextArea();  
  114.         try {  
  115.             while ( true ){  
  116.                 info = dis.readUTF();  
  117.                 ta.append("对方说: "  + info +  "\n" );  
  118.                 if (info.equals( "bye" )){  
  119.                     client.close();  
  120.                     System.exit(0 );  
  121.                 }  
  122.             }         
  123.         }catch  (IOException e) {  
  124.             e.printStackTrace();          
  125.         }     
  126.     }     
  127. }  

多用户聊天室程序

Java代码  收藏代码
  1. import  java.io.*;  
  2. import  java.net.*;  
  3. import  java.awt.*;  
  4. import  java.awt.event.*;  
  5. public   class  ChatClient {  
  6.     private  String name;  
  7.     private  Socket s;  
  8.     private  DataInputStream dis;  
  9.     private  DataOutputStream dos;  
  10.     private  Frame f;  
  11.     private  TextArea ta;  
  12.     private  TextField tf;  
  13.     private   boolean  runnable =  true ;      
  14.           
  15.     public   static   void  main(String args[]) {  
  16.         ChatClient cc = new  ChatClient();  
  17.         cc.createUI();  
  18.         cc.inputName();       
  19.         cc.connect();     
  20.         cc.createThread();  
  21.     }  
  22.     public   void  createUI(){  
  23.         f = new  Frame( "Client" );  
  24.         ta = new  TextArea();  
  25.         ta.setEditable(false );  
  26.         tf = new  TextField();  
  27.         Button send = new  Button( "Send" );  
  28.         Panel p = new  Panel();  
  29.         p.setLayout(new  BorderLayout());  
  30.         p.add(tf,"Center" );  
  31.         p.add(send,"East" );  
  32.         f.add(ta,"Center" );  
  33.         f.add(p,"South" );  
  34.         MyClientListener listener = new  MyClientListener( this );  
  35.         send.addActionListener(listener);  
  36.         tf.addActionListener(listener);  
  37.         f.addWindowListener(new  WindowAdapter(){  
  38.             public   void  windowClosing(WindowEvent e){  
  39.                 ChatClient.this .shutDown();   
  40.             }     
  41.         });  
  42.         f.setSize(400 , 400 );  
  43.         f.setLocation(600 , 0 );  
  44.         f.setVisible(true );   
  45.         tf.requestFocus();  
  46.     }  
  47.     public   void  inputName(){  
  48.         String name = javax.swing.JOptionPane.showInputDialog("Input Your Name:" );  
  49.         this .setName(name);   
  50.         f.setTitle(name);  
  51.     }  
  52.     public   void  connect(){  
  53.         try  {         
  54.             s = new  Socket( "127.0.0.1" , 9999 );  
  55.             dos = new  DataOutputStream(s.getOutputStream());  
  56.             dis = new  DataInputStream(s.getInputStream());  
  57.             dos.writeUTF(name);  
  58.         }catch  (IOException e) {  
  59.             e.printStackTrace();          
  60.         }  
  61.     }     
  62.     public   void  createThread(){  
  63.         MyClientReader reader = new  MyClientReader( this );  
  64.         reader.start();   
  65.     }  
  66.     public   void  stop(){  
  67.         runnable = false ;     
  68.     }  
  69.     public   void  shutDown(){  
  70.         try {  
  71.             dos.writeUTF("bye" );  
  72.             ta.append("Exit in 5 seconds!" );  
  73.             this .stop();              
  74.             Thread.sleep(5000 );  
  75.             dis.close();  
  76.             dos.close();  
  77.             s.close();  
  78.         }catch (Exception e){  
  79.         }  
  80.         System.exit(0 );                       
  81.     }  
  82.     public   boolean  getRunnable(){  
  83.         return  runnable;  
  84.     }             
  85.     public   void  setName(String name){  
  86.         this .name = name;  
  87.     }  
  88.     public  DataInputStream getDataInputStream(){  
  89.         return  dis;   
  90.     }  
  91.     public  DataOutputStream getDataOutputStream(){  
  92.         return  dos;   
  93.     }  
  94.     public  TextArea getTextArea(){  
  95.         return  ta;    
  96.     }  
  97.     public  TextField getTextField(){  
  98.         return  tf;    
  99.     }  
  100. }  
  101.   
  102. class  MyClientListener  implements  ActionListener{  
  103.       
  104.     private  ChatClient client;    
  105.     public  MyClientListener(ChatClient client){  
  106.         this .client = client;  
  107.     }  
  108.     public   void  actionPerformed(ActionEvent e){  
  109.         TextField tf = client.getTextField();  
  110.         String info = tf.getText();  
  111.         try {  
  112.             client.getDataOutputStream().writeUTF(info);      
  113.         }catch  (IOException e1) {  
  114.             e1.printStackTrace();         
  115.         }  
  116.         if (info.equals( "bye" )){  
  117.             client.shutDown();    
  118.         }  
  119.         tf.setText("" );  
  120.         tf.requestFocus();        
  121.     }     
  122. }  
  123.   
  124. class  MyClientReader  extends  Thread{  
  125.     private  ChatClient client;  
  126.     public  MyClientReader(ChatClient client){  
  127.         this .client = client;     
  128.     }  
  129.     public   void  run(){  
  130.         String info;  
  131.         DataInputStream dis = client.getDataInputStream();  
  132.         TextArea ta = client.getTextArea();  
  133.         try {  
  134.             while (client.getRunnable()){  
  135.                 info = dis.readUTF();  
  136.                 ta.append(info + "\n" );  
  137.             }         
  138.         }catch  (IOException e) {  
  139.         }     
  140.     }     
  141. }  

 

Java代码  收藏代码
  1. import  java.io.*;  
  2. import  java.net.*;  
  3. import  java.util.*;  
  4. public   class  ChatServer {  
  5.     public   static   void  main(String args[]) {  
  6.         Hashtable<String,DataOutputStream> userList = new  Hashtable<String,DataOutputStream>();   
  7.         String name;  
  8.         DataInputStream dis;  
  9.         DataOutputStream dos;  
  10.         try {  
  11.             ServerSocket ss = new  ServerSocket( 9999 );  
  12.             while ( true ){  
  13.                 Socket s = ss.accept();   
  14.                 dis = new  DataInputStream(s.getInputStream());  
  15.                 dos = new  DataOutputStream(s.getOutputStream());  
  16.                 name = dis.readUTF();  
  17.                 userList.put(name,dos);  
  18.                 new  MyServerReader(name,dis,userList).start();  
  19.             }  
  20.         }catch (Exception e){  
  21.             e.printStackTrace();      
  22.         }  
  23.     }  
  24. }  
  25.   
  26. class  MyServerReader  extends  Thread{  
  27.     private  String name;  
  28.     private  DataInputStream dis;  
  29.     private  Hashtable<String,DataOutputStream> userList;  
  30.     public  MyServerReader(String name,DataInputStream dis,Hashtable<String,DataOutputStream> userList ){  
  31.         this .name = name;  
  32.         this .dis = dis;   
  33.         this .userList = userList;  
  34.     }  
  35.     public   void  run(){  
  36.         String info;  
  37.         try {  
  38.             transmitMessage(name + " in!" , "--Server Info--" );     
  39.             while ( true ){  
  40.                 info = dis.readUTF();  
  41.                 if (info.equals( "bye" )){  
  42.                     DataOutputStream dos = (DataOutputStream)(userList.get(name));  
  43.                     Thread.sleep(1000 );  
  44.                     dos.close();  
  45.                     dis.close();  
  46.                     userList.remove(name);  
  47.                     transmitMessage(name + " out!" , "--Server Info--" );    
  48.                     break ;  
  49.                 }else   if (info.length()> 0 ){  
  50.                     transmitMessage(info,name);   
  51.                 }  
  52.             }         
  53.         }catch  (Exception e) {  
  54.         }  
  55.     }   
  56.     public   void  transmitMessage(String msg,String name){  
  57.         Collection doses = userList.values();  
  58.         DataOutputStream dos;  
  59.         for (Object o: doses){  
  60.             dos = (DataOutputStream)o;  
  61.             try {  
  62.                 dos.writeUTF(name + ":"  + msg);  
  63.             }catch (Exception e){  
  64.             }  
  65.         }             
  66.     }         
  67. }  

 非阻塞式Socket通信

阻塞通信意味着通信方法在尝 试访问套接字或者读写数据时阻塞了对套接字的访问。在 JDK 1.4 之前,绕过 阻塞限制的方法是无限制地使用线程,但这样常常会造成大量的线程开销,对系统的性能和可伸缩性产生影响。java.nio 包改变了这种状况,允许服务器有效地使用 I/O 流,在合理的时间内处理所服务的客户请求。
没有非阻塞通信,这个过程就像我所喜欢说的“为所欲 为”那样。基本上,这个过程就是发送和读取任何能够发送/读取的东西。如果没有可以读取的东西,它就中止读操作,做其他的事情直到能够读取为止。当发送数 据时,该过程将试图发送所有的数据,但返回实际发送出的内容。可能是全部数据、部分数据或者根本没有发送数据。
阻塞与非阻塞相比确实有一些优点, 特别是遇到错误控制问题的时候。在阻塞套接字通信中,如果出现错误,该访问会自动返回标志错误的代码。错误可能是由于网络超时、套接字关闭或者任何类型的 I/O 错误造成的。在非阻塞套接字通信中,该方法能够处理的唯一错误是网络超时。为了检测使用非阻塞通信的网络超时,需要编写稍微多一点的代码,以确定自从上一 次收到数据以来已经多长时间了
哪种方式更好取决于应用程序。如果使用的是同步通信,如果数据不必在读取任何数据之前处理的话,阻塞通信更好一些,而非阻塞通信则提供了处理任何已经读取的数据的机会。而异步通信,如 IRC 和聊天客户机则要求非阻塞通信以避免冻结套接字。

使用非阻塞实现I/O实现多用户聊天.

Java代码  收藏代码
  1. import  java.net.*;  
  2. import  java.nio.*;  
  3. import  java.nio.channels.*;  
  4. import  java.nio.charset.*;  
  5. import  java.awt.*;  
  6. import  java.awt.event.*;  
  7.   
  8. public   class  ChatClient {  
  9.     private  SocketChannel sc =  null ;  
  10.     private  String name =  null ;  
  11.     private  Frame f;  
  12.     private  TextArea ta;  
  13.     private  TextField tf;  
  14.     private   boolean  runnable =  true ;  
  15.   
  16.     public   static   void  main(String[] args){  
  17.         ChatClient cc = new  ChatClient();  
  18.         cc.createUI();  
  19.         cc.inputName();  
  20.         cc.connect();  
  21.         new  ReceiveThread(cc,cc.getTextArea()).start();  
  22.     }  
  23.     public  SocketChannel getSc(){  
  24.         return  sc;    
  25.     }  
  26.     public   void  setName(String name){  
  27.         this .name = name;  
  28.     }  
  29.     public  TextArea getTextArea(){  
  30.         return  ta;    
  31.     }  
  32.     public  TextField getTextField(){  
  33.         return  tf;    
  34.     }  
  35.     public   boolean  getRunnable(){  
  36.         return  runnable;  
  37.     }     
  38.     public   void  stop(){  
  39.         runnable = false ;     
  40.     }  
  41.       
  42.     public   void  shutDown(){  
  43.         try {  
  44.             sc.write(ByteBuffer.wrap("bye" .getBytes( "GBK" )));     
  45.             ta.append("Exit in 5 seconds!" );  
  46.             this .stop();  
  47.             Thread.sleep(5000 );  
  48.             sc.close();  
  49.         }catch (Exception e){  
  50.             e.printStackTrace();      
  51.         }  
  52.         System.exit(0 );  
  53.     }  
  54.       
  55.     public   void  createUI(){  
  56.         f = new  Frame( "Client" );  
  57.         ta = new  TextArea();  
  58.         ta.setEditable(false );  
  59.         tf = new  TextField();  
  60.         Button send = new  Button( "Send" );  
  61.         Panel p = new  Panel();  
  62.         p.setLayout(new  BorderLayout());  
  63.         p.add(tf,"Center" );  
  64.         p.add(send,"East" );  
  65.         f.add(ta,"Center" );  
  66.         f.add(p,"South" );  
  67.         MyClientListener listener = new  MyClientListener( this );  
  68.         send.addActionListener(listener);  
  69.         tf.addActionListener(listener);  
  70.         f.addWindowListener(new  WindowAdapter(){  
  71.             public   void  windowClosing(WindowEvent e){  
  72.                 ChatClient.this .shutDown();  
  73.             }     
  74.         });  
  75.         f.setSize(400 , 400 );  
  76.         f.setLocation(600 , 0 );  
  77.         f.setVisible(true );   
  78.         tf.requestFocus();  
  79.     }  
  80.       
  81.     public   boolean  connect(){  
  82.         try {  
  83.             sc = SocketChannel.open();  
  84.             //"zlg"为目标计算机名   
  85.             InetSocketAddress isa = new  InetSocketAddress( "zlg" , 8888 );  
  86.             sc.connect(isa);  
  87.             sc.configureBlocking(false );  
  88.             sc.write(ByteBuffer.wrap(name.getBytes("GBK" )));  
  89.         }catch (Exception e){  
  90.             e.printStackTrace();      
  91.         }  
  92.         return   true ;  
  93.     }  
  94.       
  95.     public   void  inputName(){  
  96.         String name = javax.swing.JOptionPane.showInputDialog("Input Your Name:" );  
  97.         this .setName(name);   
  98.         f.setTitle(name);  
  99.     }  
  100. }  
  101.   
  102. class  MyClientListener  implements  ActionListener{  
  103.     private  ChatClient client;    
  104.     public  MyClientListener(ChatClient client){  
  105.         this .client = client;  
  106.     }  
  107.     public   void  actionPerformed(ActionEvent e){  
  108.         TextField tf = client.getTextField();  
  109.         String info = tf.getText();  
  110.         if (info.equals( "bye" )){  
  111.             client.shutDown();    
  112.         }else {  
  113.             try {  
  114.                 client.getSc().write(ByteBuffer.wrap(info.getBytes("GBK" )));  
  115.             }catch  (Exception e1) {  
  116.                 e1.printStackTrace();         
  117.             }         
  118.         }  
  119.         tf.setText("" );  
  120.         tf.requestFocus();        
  121.     }     
  122. }  
  123.   
  124. class  ReceiveThread  extends  Thread{  
  125.     private  ChatClient client;  
  126.     private  TextArea ta;  
  127.           
  128.     public  ReceiveThread(ChatClient client,TextArea ta){  
  129.         this .client = client;     
  130.         this .ta = ta;  
  131.     }  
  132.     public   void  run(){  
  133.         SocketChannel sc = client.getSc();  
  134.         ByteBuffer byteBuffer = ByteBuffer.allocate(2048 );  
  135.         CharBuffer charBuffer = null ;  
  136.         Charset charset = Charset.forName("GBK" );  
  137.         CharsetDecoder decoder = charset.newDecoder();  
  138.         String msg = null ;  
  139.         int  n =  0 ;  
  140.         try {  
  141.             while (client.getRunnable()){  
  142.                 n = sc.read(byteBuffer);  
  143.                 if (n> 0 ){  
  144.                     byteBuffer.flip();  
  145.                     charBuffer = decoder.decode(byteBuffer);  
  146.                     msg = charBuffer.toString();  
  147.                     ta.append(msg + "\n" );  
  148.                 }  
  149.                 byteBuffer.clear();  
  150.                 Thread.sleep(500 );  
  151.             }  
  152.         }catch (Exception e){  
  153.             e.printStackTrace();  
  154.             System.exit(0 );   
  155.         }  
  156.     }  
  157. }  

 

Java代码  收藏代码
  1. import  java.io.*;  
  2. import  java.nio.*;  
  3. import  java.nio.channels.*;  
  4. import  java.nio.charset.*;  
  5. import  java.net.*;  
  6. import  java.util.*;  
  7.   
  8.   
  9. public   class  ChatServer{  
  10.     private  Selector selector =  null ;  
  11.     private  ServerSocketChannel ssc =  null ;  
  12.     //服务器端通信端口号   
  13.     private   int  port =  8888 ;  
  14.     //在线用户列表   
  15.     private  Hashtable<String,SocketChannel> userList =  null ;     
  16.       
  17.     public  ChatServer(){}      
  18.     public  ChatServer( int  port){  
  19.         this .port = port;  
  20.     }  
  21.       
  22.     //初始化服务器   
  23.     public   void  init(){  
  24.         try {  
  25.             //创建选择器对象   
  26.             selector = Selector.open();  
  27.             //创建ServerSocketChannel   
  28.             ssc = ServerSocketChannel.open();  
  29.             //设置ServerSocketChannel为非阻塞模式   
  30.             ssc.configureBlocking(false );  
  31.             InetAddress ia = InetAddress.getLocalHost();  
  32.             InetSocketAddress isa = new  InetSocketAddress(ia,port);  
  33.             //将与本通道相关的服务器套接字对象帮定到指定地址和端口   
  34.             ssc.socket().bind(isa);  
  35.             //创建在线用户列表   
  36.             userList = new  Hashtable<String,SocketChannel>();  
  37.         }catch (IOException e){  
  38.             e.printStackTrace();      
  39.         }  
  40.     }  
  41.       
  42.     //启动服务器   
  43.     public   void  start(){  
  44.         try {  
  45.             //将ServerSocketChannel注册到Selector上,准备接收新连接请求   
  46.             SelectionKey acceptKey = ssc.register(selector, SelectionKey.OP_ACCEPT );  
  47.             SocketChannel sc;  
  48.             int  n;    
  49.             String name;    //用户名   
  50.             String msg;     //用户发言信息   
  51.             while  ( true ){     
  52.                 //选择当前所有处于就绪状态的通道所对应的选择键,并将这些键组成已选择键集   
  53.                 n = selector.select(); //n为已选择键集中键的个数   
  54.                 if (n >  0  ){  
  55.                     //获取此选择器的已选择键集。   
  56.                     Set readyKeys = selector.selectedKeys();   
  57.                     Iterator it = readyKeys.iterator();   
  58.                     //遍历当前已选择键集   
  59.                     while  (it.hasNext()) {  
  60.                         SelectionKey key = (SelectionKey)it.next();  
  61.                         //从当前已选择键集中移除当前键,避免重复处理   
  62.                         it.remove();  
  63.                         //如果当前键对应的通道已准备好接受新的套接字连接   
  64.                         if  (key.isAcceptable()) {  
  65.                             //获取当前键对应的可选择通道(ServerSocketChannel)     
  66.                             ssc = (ServerSocketChannel) key.channel();  
  67.                             //接收新的套接字连接请求,返回新建的SocketChannel   
  68.                             sc = (SocketChannel) ssc.accept();  
  69.                             //如果有新用户接入   
  70.                             if (sc !=  null ){  
  71.                                 //接收新上线用户姓名   
  72.                                 name = readMessage(sc);  
  73.                                 //设置新建的SocketChannel为非阻塞模式   
  74.                                 sc.configureBlocking(false );  
  75.                                 //将新建的SocketChannel注册到Selector上,准备进行数据"写"操作,   
  76.                                 //并将当前用户名以附件的方式附带记录到新建的选择键上。   
  77.                                 SelectionKey newKey = sc.register(selector,SelectionKey.OP_WRITE,name);   
  78.                                 //将新上线用户信息加入到在线用户列表   
  79.                                 userList.put(name,sc);  
  80.                                 //发送"新用户上线"通知   
  81.                                 transmitMessage(name + " in!" , "--Server Info--" );  
  82.                             }  
  83.                         }  
  84.                         //否则,如果当前键对应的通道已准备好进行"写"操作   
  85.                         else   if  (key.isWritable()) {  
  86.                             //获取当前键对应的可选择通道(SocketChannel)    
  87.                             sc = (SocketChannel)key.channel();  
  88.                             //接收该通道相应用户的发言信息   
  89.                             msg = readMessage(sc);  
  90.                             //获取选择键上附带记录的当前用户名   
  91.                             name = key.attachment().toString();  
  92.                             //如果用户提出要下线   
  93.                             if (msg.equals( "bye" )){  
  94.                                 //从在线用户列表中移除当前用户   
  95.                                 userList.remove(name);  
  96.                                 //注销当前选择键对应的注册关系   
  97.                                 key.cancel();  
  98.                                 //关闭当前可选择通道    
  99.                                 sc.close();  
  100.                                 //发送"用户下线"通知   
  101.                                 transmitMessage(name + " out!" , "--Server Info--" );  
  102.                             }  
  103.                             //否则,如果接收到的用户发言信息非空("")   
  104.                             else   if (msg.length() >  0 ){  
  105.                                 //转发用户发言信息   
  106.                                 transmitMessage(msg,name);  
  107.                             }  
  108.                         }  
  109.                     }  
  110.                 }  
  111.                 //延时循环,降低服务器端处理负荷   
  112.                 Thread.sleep(500 );  
  113.             }  
  114.         }catch (Exception e){  
  115.             e.printStackTrace();      
  116.         }  
  117.     }  
  118.   
  119.     //转发用户发言信息   
  120.     public   void  transmitMessage(String msg,String name){  
  121.         try {  
  122.             ByteBuffer buffer = ByteBuffer.wrap((name + ":"  + msg).getBytes( "GBK" ));  
  123.             Collection channels = userList.values();  
  124.             SocketChannel sc;  
  125.             for (Object o:channels){  
  126.                 sc = (SocketChannel)o;  
  127.                 sc.write(buffer);  
  128.                 buffer.flip();  
  129.             }  
  130.         }catch (Exception e){  
  131.             e.printStackTrace();  
  132.         }  
  133.     }  
  134.     
  135.     //接收用户发言信息   
  136.     public  String readMessage(SocketChannel sc){  
  137.         String result = null ;  
  138.         int  n =  0 ;  
  139.         ByteBuffer buf = ByteBuffer.allocate(1024 );  
  140.         try {  
  141.             n = sc.read(buf);  
  142.             buf.flip();  
  143.             Charset charset = Charset.forName("GBK" );  
  144.             CharsetDecoder decoder = charset.newDecoder();  
  145.             CharBuffer charBuffer = decoder.decode(buf);  
  146.             result = charBuffer.toString();  
  147.         }catch (IOException e){  
  148.             e.printStackTrace();  
  149.         }  
  150.         return  result;  
  151.     }  
  152.   
  153.     public   static   void  main(String args[]){  
  154.         ChatServer server = new  ChatServer();  
  155.         server.init();  
  156.         server.start();  
  157.     }  

分享到:
评论

相关推荐

    TCPIP网络编程

    最适合入门的网络编程入门书,初学者必看

    C++网络编程文档

    C++网络编程是计算机科学中的一个重要领域,它允许开发者创建能够通过网络进行通信的应用程序。这份"C++网络编程文档"涵盖了这一主题的广泛内容,旨在帮助程序员深入理解并掌握网络编程的基本概念和技术。 首先,...

    Linux网络编程

    《Linux网络编程》内容简介:Linux是目前最流行的开源操作系统,网络功能在Linux下占有核心的地位。《Linux网络编程》循序渐进地从应用层到Linux内核、从基本知识点到综合案例,向读者介绍如何在Linux下进行网络程序...

    UNIX网络编程

    对于开发网游服务器的人开说,是本非常好的书,书中核心的学习部分还是SOCKET 套接口基本API相关的使用和注意细节,其他部分...网络游戏服务端编程其实针对网络底层所需要的技术点并不多,因此此书只需要针对性的学习。

    java网络编程

    java网络编程包括socket tcp/udp io/nio讲解 http协议 jdbc rmi java的安全框架等知识

    visual c++网络编程开发与实战 光盘

    好神奇的网盘 pan.baidu.com/s/14rAaUiTx_YQezyFle1MTqg?pwd=8fnd 提取码: 8fnd

    网络编程111111111111

    网络编程111111111111

    计算机网络编程

    该资源是面向计算机网络编程的,利用套接字来进行处理的工程。

    C#网络编程高级篇之网页游戏辅助程序设计.part3_C#_网络编程_

    这本书是关于c#网络编程的,关于c#入门的书有很多,但是关于c#网络编程的并不多,很多教材中虽有涉及网络编程但都是泛泛而谈,很多理论概念掺杂在其中,让人很难理解,而这本不同,含有非常多的例子,从简到深,甚至...

    java网络编程第四版pdf

    《Java网络编程(第四版)》是一本深入探讨Java在互联网环境下的编程技术的经典书籍。本书旨在帮助读者理解和掌握如何利用Java语言进行高效、安全的网络通信。书中内容覆盖了从基本的网络概念到复杂的多线程编程,是...

    WinSock网络编程经络.pdf

    WinSock网络编程经络 随书源码 本书专门讨论Windows网络编程技术。内容包括NetBIOS和Windows重定向器方法、Winsock方法、客户端远程访问服务器方法。

    C-C++网络编程基础:从Socket到高性能网络库的选择.md

    C/C++ 网络编程的基础知识,从 Socket 编程到高性能网络库的选择。首先,文章解释了 Socket 的基本概念及其在网络通信中的作用,包括 TCP 和 UDP 两种主要协议的区别和用法。接着,文章描述了 Socket 编程的典型工作...

    Linux网络编程,包括tcp/upd,select/poll/epoll/pdf

    linux网络编程 pdf # Linux网络编程基础 Linux网络编程是指在Linux操作系统上开发网络应用程序的过程。它主要涉及到TCP/UDP协议以及select/poll/epoll等多路复用技术。 TCP/UDP协议是网络通信的基础,其中TCP协议...

    网络编程课件

    网络编程课件,包括计算机网络基本知识点介绍 主要是windows socket编程技术

    TCP IP网络编程

    扫描版 超清百度网盘资源!!! 为初学者准备的网络编程! 韩国TCP/IP经典教程!... 本书针对网络编程初学者,面向具备C语言基础的套接字网络编程学习者,适合所有希望学习Linux和Windows网络编程的人。

    Java网络编程(第4版)PDF

    《Java网络编程(第4版)》是一本深入探讨Java平台上的网络编程技术的专业书籍,适合想要提升Java通讯技术的学者阅读。此书全面覆盖了Java网络编程的基础和高级概念,帮助开发者理解如何利用Java语言构建高效、可靠的...

    unix网络编程

    unix 网络编程,带详细书签

    Linux网络编程.rar

    linux网络编程

    Windows网络编程.pdf

    Windows 网络编程 概述 Windows 网络编程是指在 Windows 操作系统平台上进行网络编程的技术,涉及到 Windows Socket、网络协议、网络应用程序的开发等方面。 Windows 网络编程的主要目的是实现高性能的网络应用...

    PyTorch生成对抗网络编程

    PyTorch生成对抗网络编程(畅销书《Python神经网络编程》作者最新力作!用PyTorch构建自己的生成对抗网络) by 塔里克·拉希德

Global site tag (gtag.js) - Google Analytics