`
snoopy7713
  • 浏览: 1123724 次
  • 性别: 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.     }  

分享到:
评论

相关推荐

    Unix 网络编程 卷1 第三版 源代码

    《UNIX网络编程》(第1卷)(套接口API第3版)第1版和第2版由已故UNIX网络专家W. Richard Stevens博士独自编写。《UNIX网络编程》(第1卷)(套接口API第3版)是3版,由世界著名网络专家Bill Fenner和Andrew M. Rudoff执笔,...

    Linux网络编程 Linux网络编程.TXT

    Linux网络编程 Linux网络编程 Linux网络编程

    网络编程之发送结构体.zip

    网络编程之发送结构体网络编程之发送结构体网络编程之发送结构体网络编程之发送结构体网络编程之发送结构体网络编程之发送结构体网络编程之发送结构体网络编程之发送结构体网络编程之发送结构体网络编程之发送结构体...

    网络编程实用教程(程序源代码).zip

    全书分为10章,第1章介绍网络编程的基本概念及模式,第2章介绍套接字网络编程基础,第3章介绍Windows环境的WinSock编程基础,第4章介绍MFC编程,第5章介绍MFC WinSock类的编程,第6章介绍WinInet编程,第7章介绍...

    网络编程合集 TCP-IP详解 windows Linux UNIX Ace 网络编程 7_2

    网络编程合集 TCP-IP详解 windows Linux UNIX Ace 网络编程 搜索关键字:网络编程 TCP-IP详解 windows Linux UNIX 网络编程1_TCP-IP详解卷1.rar 网络编程2_TCP-IP详解卷2-1.rar 网络编程3_windows网络编程电子书及...

    linux C语言 网络编程教程及源码

    linux C语言 网络编程教程及源码 一、网络应用层编程 1、Linux网络编程01——网络协议入门 2、Linux网络编程02——无连接和面向连接的区别 3、Linux网络编程03——字节序和地址转换 4、Linux网络编程04——套接字 5...

    Linux网络编程.pdf

    Linux网络编程

    UNIX网络编程(第1卷)-源码

    《UNIX网络编程 卷1:套接字联网API(第2版)》是一部UNIX网络编程的经典之作。书中全面深入地介绍了如何使用套接字API进行网络编程。全书不但介绍了基本编程内容,还涵盖了与套接字编程相关的高级主题,对于客户/...

    UNIX网络编程_卷2_进程间通信

    《UNIX网络编程.卷2:进程间通信(第2版)》是一部UNIX网络编程的经典之作!进程间通信(IPC)几乎是所有Unix程序性能的关键,理解IPC也是理解如何开发不同主机间网络应用程序的必要条件。《UNIX网络编程.卷2:进程间...

    TCP IP网络编程

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

    C++网络编程文档

    C++网络编程电子书,包括了网络编程的各个方面,内含19个文档。

    C#网络编程技术教程

    《C#网络编程技术教程》注重理论与实践的结合、循序渐进的教学方法。系统介绍了C#网络编程的相关知识,使读者能够快速掌握基于C#的网络应用开发技术。根据应用的需要,《C#网络编程技术教程》在内容安排上对C#基础...

    Linux网络编程

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

    UNIX网络编程卷1代码.rar

    UNIX网络编程卷1代码.rarUNIX网络编程卷1代码.rar

    ACE网络编程ACE网络编程

    ACE网络编程ACE网络编程;ACE网络编程ACE网络编程;ACE网络编程ACE网络编程

    C#网络编程技术教程\

    C#网络编程技术教程rC#网络编程技术教程

    陈硕 网络编程实践 视频

    是一门以讲解实例为主的课程,每一节都讲一两个网络编程的例子程序,课程偏重 Linux 服务端 TCP 网络编程。如有侵权,资源来自网络,低分分享,联系删除

    Java网络编程/Java网络编程实例

    《Java网络编程》,附带《Java网络编程实例》和阅读器,欢迎下载

    网络编程3HTTP编程 网络编程3HTTP编程

    网络编程3HTTP编程 网络编程3HTTP编程 网络编程3HTTP编程

    UNIX网络编程一全套源码

    UNIX网络编程卷一:套接口编程的全套源码!是学习UNIX/LINUX网络编程的经典资料!

Global site tag (gtag.js) - Google Analytics