隨筆-159  評論-114  文章-7  trackbacks-0

          一臺主機有個IP地址(邏輯地址),MAC(物理地址)。用IP可以找到一臺主機。

          能交換數據的是進程,進程之間交換數據,不是計算機。

          一個程序.exe,靜態的概念,一個進程,在內存中,運行態的概念。

          某些進程會占用固定的端口,進程與端口對應。

          把一個端口和進程建立聯系的叫做綁定。

          FTP《=》端口21

          進程間通訊是兩個端口建立連接。

          由于機器通訊,要有相同的語言,為保證數據正常交互,預先約定好協議。

          網絡體系架構,解決異構性問題采用的是分層方法--把復雜網絡互聯問題劃分為若干較小的,單一的問題。

          分層-〉人解決復雜網絡問題的一般思路。

          OSI :

          對等層不允許直接通訊,嚴格單項依賴,上層依賴下層提供的服務,下層不依賴于上層工作。

          對等層是虛擬連接。

          網絡層----〉IP協議(尋址)(路由)

          傳輸層----〉TCP傳輸控制協議,UDP用戶數據報協議

          TCP有很大開銷,三次握手,保證數據可靠傳輸,

          UDP用于對實時性要求的應用。他是把大塊數據分成小的數據報,只發數據報,數據報自己負責尋址,所以不一定路徑一樣,順序可能亂。



          數據封裝的概念,下一層對上層數據按照自己的格式進行再次封裝,封裝就是在數據前面加上特定的協議頭部信息。數據打包

          Untitled-1.jpg


          上層向一層一次,就封裝一次,到另外一層就是反向的,解封一次。

          TCP/IP

          應用層
          傳輸層
          網絡層
          網絡接口

          端口是一種抽象的軟件結構,與協議相關。

          TCP:23和UDP:23不相關。


          IP+Port就是一個Socket,是一個對象的概念。就好像電話機,電話號碼和分機號

          Socket是傳輸層的。網絡編程要注意在哪一個層次編程。

          基于TCP,java.net.ServerSocket,服務器進程。構造函數一個端口號

          Socket s  = ServerSocket.accept(),阻塞方法,可以返回一個與聯入的客戶端Socket對應的Socket。

          客戶端:Socket s1 = new Socket("127.0.0.1",6666);

          s和s1不同。

          獲得數據,s.getInputStream(),s.getOutputStream()

          s.close(),關閉socket,會自動關閉流,至少這時流不再可用。

          import java.io.*;
          import java.net.*;

          public class Server{
              
          public static void main(String[] args) throws Exception
              
          {
                  ServerSocket ss 
          = new ServerSocket(8000);
                  Socket s 
          = ss.accept();        
                  PrintWriter out 
          = new PrintWriter(s.getInputStream());        
                  out.println(
          "Server started!");
                  out.flush();
                  
                  s.close();
                  ss.close();
              }

          }

           

          import java.io.*;
          import java.net.*;

          public class Client{
              
              
          public static void main(String[] args) throws Exception
              
          {
                  Socket s 
          = new Socket("127.0.0.1",8000);
                  BufferedReader in 
          = new BufferedReader(new InputStreamReader(s.getInputStream()));
                  String str 
          = in.readline();
                  System.out.println(str);
                  
                  BufferedReader br 
          = new BufferedReader(new InputStreamReader(System.in));
                  br.readline();
              }

          }

          以上是最簡單的Server和Client。

          以下是本人編的多人群聊的聊天室。

          import java.io.*;
          import java.net.*;
          import java.util.*;

          public class NewServer{
            
          private ServerSocket ss;
            
          private int port = 7777;//默認端口
            private static int online = 0;//當前服務在線人數
            
            
          private List threadList;//客戶端連入Server后,啟動過的線程的集合,以便管理,群發
            final static PrintWriter sysout;//服務器本地輸出,無用,直接System.out,沒問題。
            
            
          static{
              sysout 
          = new PrintWriter(System.out,true);
            }

            
            
          public NewServer(int port)
            
          {
              
          if(port!=0){//參數為0,采用默認端口
                this.port = port;
              }

              
          try{
                ss 
          = new ServerSocket(this.port);//綁定
                threadList = new ArrayList();
                sysout.println(
          "Start service on " + this.port);
                
          while(true)//死循環,用于處理客戶端的連入,并啟動獨立線程,與客戶端交換信息
                {
                  Transmit t 
          = new Transmit(ss.accept());//阻塞住,直到有客戶端連接
                  threadList.add(t);//將即將啟動的線程,加入list
                  t.start();
                }

              }
          catch(Exception e)
              
          {
                  e.printStackTrace();
              }

            }

            
            
          /**
            *
            * 私有成員內部類(便于訪問外部類私有屬性),如果改為頂級類沒有問題,封裝了服務器與客戶端交換數據的獨立線程操作。
            
          */
            
            
          private class Transmit extends Thread{
              
          private BufferedReader input;//帶緩沖的字符流,作為輸入流,從中讀取發送到服務器的信息
              private PrintWriter output;//帶緩沖的字符流,作為輸出流,輸入字符
              private String serverinfo = System.getProperty("os.name")+" "+System.getProperty("os.arch")+" "+System.getProperty("os.version");
              
          private Socket client;//ss.accept()返回的socket
              private boolean quit = false;//判斷是否退出
              
              
          public Transmit(Socket sock){
                
          this.client = sock;
                
          try{
                  
          this.input = new BufferedReader(new InputStreamReader(client.getInputStream(),"gb2312"));
                  
          this.output = new PrintWriter(client.getOutputStream(),true);//auto flush
                  output.println("Now,Server has " + (online) + " people online!");
                  output.println(serverinfo);
                }
          catch(Exception ex){}
              }

              
              
          public void run(){
                
          try{
                  
          while(!quit)
                  
          {           
                    String line 
          = input.readLine();
                    
          if(line == null) quit = true;
                    
          else{
                      sysout.println(
          ""+new Date().toString()+"Receive word From : "+client.getInetAddress()+" ]: " + line);//本地輸出,可以重定向到文件
                      if(line.trim().equalsIgnoreCase("EXIT"))
                      
          {
                        output.println(
          "See you");
                        quit 
          = true;              
                      }

                      
          else
                          sendToOtherMsg(client.getInetAddress().toString(),line);
          //遍歷threadlist,群發信息
                    }

                  }

                  online
          --;
                }

                
          catch(SocketException e)
                
          {
                    
          if(e.getMessage().indexOf("Connection reset")!=-1)//客戶端退出
                    {
                        sysout.println(client.getInetAddress() 
          + "offline");
                        online
          --;
                    }

                }

                
          catch(Exception e)
                
          {
                  e.printStackTrace();
                }

                
          finally
                
          {
                    
          try{
                        client.close();
          //socket會關閉所打開的流,不要強行關閉流,會有問題。
                    }
          catch(Exception e){}
                }

              }

              
              
          //發送信息給其他線程所通訊的客戶端
              private void sendToOtherMsg(String ip,String msg)
                
          {
                  Iterator it 
          = threadList.iterator();
                  
          while(it.hasNext())
                  
          {
                      Transmit t 
          = ((Transmit)it.next());
                      
          if(!t.isAlive()) //如果線程已經進入死亡狀態,也就是線程已經運行完畢,remove掉
                      {
                              it.remove();
                              
          continue;
                      }

                    t.sendIt(
          "["+ip+"]: "+msg);
                    
                  }

                }

                
                
          private void sendIt(String msg)
              
          {
                output.println(msg);      
              }

                
            }

            
            
          public static void main(String[] args)
            
          {
                
          new NewServer(61248);
            }

          }

          客戶端:

          import java.io.*;
          import java.net.*;
          import java.util.*;
          import javax.swing.*;
          import java.awt.*;
          import java.awt.event.*;
          public class ChatRoomClient{
            
          private JTextArea jta;
            
          private JTextField jtf;
            
          private JFrame f;
            
          private Socket conn;
            
          private BufferedReader echo;
            
          private PrintWriter pw;
            
          private boolean done = false;
            
          public ChatRoomClient(String host,int port){
              creatGUI();
              
              
          try{
                conn 
          = new Socket();
                conn.connect(
          new InetSocketAddress(host,port),10000);//Socket連接
                
                
          //通過橋轉換,將socket得到的字節輸入流按照gb2312編碼方式轉換為字符輸入流,再封裝為帶緩沖的過濾流
                echo = new BufferedReader(new InputStreamReader(conn.getInputStream(),"gb2312"));
                
                
          //直接使用PrintWriter這個過濾流封裝字節輸出流為字符流,并帶有緩沖,比BufferedWriter方法更多。
                pw = new PrintWriter(conn.getOutputStream(),true);//auto flush
                jta.append("Connected to " + conn.getInetAddress() + ":" + conn.getPort() + "\n");
                
          while(!done){
                  String info 
          = echo.readLine();
                  jta.append(info
          +"\n");
                }

                jta.append(
          "client will be closed in 2s.\n");
                Thread.sleep(
          2000);
                System.exit(
          0);
              }

              
          catch(SocketException ex)
              
          {
                
          if(ex.getMessage().indexOf("Connection reset")!=-1)//服務器關閉
                  jta.append("Server down!\n");
                
          if(ex.getMessage().indexOf("Connection refused: connect")!=-1)//服務器不通
                  jta.append("connection refused!\nplease check network!\n");
              }

              
          catch(Exception ex)
              
          {
                ex.printStackTrace();
              }

              
          finally
              
          {
                
          try{
                  conn.close();
          //只關閉socket
                }
          catch(Exception ex)
                
          {
                }
             
              }

            }

            
            
          private void creatGUI()
            
          {
              jta
          =new JTextArea();
              jta.setEditable(
          false);
              jtf
          =new JTextField();
              f
          =new JFrame("Chat Client");
              JScrollPane jp
          =new JScrollPane(jta);//構建帶滑動條的JTextField
              f.getContentPane().add(jp);
              f.getContentPane().add(jtf,
          "South");//JDK 1.5取消getContentPane,直接add沒問題
              f.setSize(600,400);
              f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
          //右上角的叉子,生效,關閉窗體
              f.setVisible(true);//設置可見,否則不可見
              
              jtf.addActionListener(
          new ActionListener(){//添加事件處理
                public void actionPerformed(ActionEvent e){
                  String s
          =jtf.getText();
                  
          if(s.trim().equalsIgnoreCase("EXIT"))
                    done 
          = true;//讓主線程的while退出,進而結束Client
                  pw.println(s);//利用輸出流,輸出到服務器信息。
                  jtf.setText("");
                }

              }
          );
            }

            
            
          public static void main(String[] args){
              ChatRoomClient c
          =new ChatRoomClient("127.0.0.1",7777);
            }

          }


            

          UDP編程

          編寫一個時間服務器,客戶端就向服務器索取一個時間。

          import java.io.*;
          import java.net.*;
          import java.util.*;

          public class Server{
              
              
          static byte[] getTime()
                  Date d
          = new Date(); 
                  
          return d.toString().getBytes(); 
            }
           
             
              
          public static void main(String[] args) throws Exception
              
          {
                  
                      DatagramPacket inDataPacket 
          = null;
                       DatagramPacket outDataPacket 
          = null;
                      
          byte[] msg= new byte[100];
                      
          byte[] time;
                      
                      InetAddress clientAddress;
                      
          int clientPort;
                      
                      
                      
                      DatagramSocket datagramSocket 
          = new DatagramSocket(13);
                      System.out.println(
          "UDP server active on port 13"); 
                      
                      
          while(true
                      
                      inDataPacket 
          = new DatagramPacket(msg, msg.length);
                      
                      
          // Get the message. 
                      datagramSocket.receive(inDataPacket); 
                      
                      String s
          =new String(inDataPacket.getData());
                      System.out.println(s);
                      
                      
          //============================================================
                      
                      
          // Retrieve return address information, including InetAddress 
                      
          // and port from the datagram packet just recieved. 
                      clientAddress = inDataPacket.getAddress(); 
                      clientPort 
          = inDataPacket.getPort(); 
                        
                      
          // Get the current time. 
                      time = getTime(); 
            
                      
          //set up a datagram to be sent to the client using the 
                      
          //current time, the client address and port 
                      outDataPacket = new DatagramPacket(time, time.length, clientAddress, clientPort); 
            
                      
          //finally send the packet 
                      datagramSocket.send(outDataPacket); 
                      
                  }
           
                      
              }

          }


          UDP的端口與TCP上的端口沒關系,端口和協議有關。

          import java.io.*;
          import java.net.*;

          public class Client{
              
              
          public static void main(String[] args) throws Exception
              
          {
                  DatagramSocket ds 
          = new DatagramSocket();
                  String s 
          = "Hello World";
                  DatagramPacket outDataPacket 
          = new DatagramPacket(s.getBytes(),s.length(),InetAddress.getLocalHost(),13);
                  ds.send(outDataPacket);
                  
                  
          byte[] msg = new byte[100];
                  String receivedMsg;
                  DatagramPacket inDataPacket 
          = new DatagramPacket(msg, msg.length);
                  ds.receive(inDataPacket);
                  
                  receivedMsg 
          = new String(inDataPacket.getData(), 0, inDataPacket.getLength()); 
              System.out.println(receivedMsg);
              
              
          //close the socket
              ds.close(); 
                  
              }

          }

          服務器需要客戶端先向服務器發送一個信息,服務器才能提供服務。再回復信息,因為UDP面向非連接的。

          Socket之間交換數據。

          交換DatagramPacket,內容在字節數據中,發送方在Pocket寫上地址和端口,send。
          接收方必須準備一個空信,以便接收內容。received,將字節數組裝滿。

          =========================================

          URL編程

          import java.io.*;
          import java.net.*;
          import java.util.*;

          public class URLConnectionTest {  
              
             
          public static void main(String[] args) {  
                 
                
          try {  
                    
                   String urlName;
                   
          if (args.length > 0) urlName = args[0];
                   
          else  urlName = "http://www.tarena.com.cn";
                   
                   
          //step 1. Create a URL
                   URL url = new URL(urlName);
                   URLConnection con 
          = url.openConnection();
                   
                   
          //step 2. Connect to the server
                   con.connect();

                   
          // print header fields

                   
          int n = 1;
                   String key;
                   
          while ((key = con.getHeaderFieldKey(n)) != null{  
                      String value 
          = con.getHeaderField(n);
                      System.out.println(key 
          + " = " + value);
                      n
          ++;
                   }


                   
          // print convenience functions
                   System.out.println();
                   System.out.println(
          "getContentType: " + con.getContentType());
                   System.out.println(
          "getContentLength: " + con.getContentLength());
                   
                   System.out.println(
          "getContentEncoding: " + con.getContentEncoding());
                   System.out.println(
          "getDate: " + con.getDate());
                   System.out.println(
          "getExpiration: " + con.getExpiration());
                   System.out.println(
          "getLastModifed: " + con.getLastModified());
                   System.out.println();

                  
          //step 3 and 4. Get an InputStream and encapsulate it
                   BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));

                   
          // print first ten lines of contents
                   String line;
                   n 
          = 1;
                   
                   
          //step 5. Read info from the stream
                   while ((line = in.readLine()) != null && n <= 100{  
                      System.out.println(line);
                      n
          ++;
                   }

                   
                   
          if (line != null) System.out.println(". . .");
                   
                }

                
          catch (IOException exception) {  
                   exception.printStackTrace();
                }

             }

          }





          posted on 2005-12-29 14:19 北國狼人的BloG 閱讀(379) 評論(1)  編輯  收藏

          評論:
          # re: Java網絡編程 2006-07-02 10:56 | Sophia
          GG,謝謝哦,你的源程序救了我一命啊!!!!  回復  更多評論
            

          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          主站蜘蛛池模板: 贡觉县| 华坪县| 高安市| 衡山县| 乌拉特前旗| 大同县| 洪雅县| 元江| 莫力| 页游| 黄大仙区| 吴旗县| 安岳县| 洪泽县| 甘南县| 甘肃省| 宜宾县| 黎川县| 新绛县| 铜川市| 蒙阴县| 开远市| 泗洪县| 同仁县| 沈阳市| 登封市| 尚志市| 会昌县| 丹凤县| 西畴县| 旬邑县| 绥芬河市| 汉寿县| 千阳县| 青海省| 平山县| 循化| 三河市| 淄博市| 双鸭山市| 郎溪县|