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

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

          能交換數(shù)據(jù)的是進程,進程之間交換數(shù)據(jù),不是計算機。

          一個程序.exe,靜態(tài)的概念,一個進程,在內(nèi)存中,運行態(tài)的概念。

          某些進程會占用固定的端口,進程與端口對應(yīng)。

          把一個端口和進程建立聯(lián)系的叫做綁定。

          FTP《=》端口21

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

          由于機器通訊,要有相同的語言,為保證數(shù)據(jù)正常交互,預(yù)先約定好協(xié)議。

          網(wǎng)絡(luò)體系架構(gòu),解決異構(gòu)性問題采用的是分層方法--把復(fù)雜網(wǎng)絡(luò)互聯(lián)問題劃分為若干較小的,單一的問題。

          分層-〉人解決復(fù)雜網(wǎng)絡(luò)問題的一般思路。

          OSI :

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

          對等層是虛擬連接。

          網(wǎng)絡(luò)層----〉IP協(xié)議(尋址)(路由)

          傳輸層----〉TCP傳輸控制協(xié)議,UDP用戶數(shù)據(jù)報協(xié)議

          TCP有很大開銷,三次握手,保證數(shù)據(jù)可靠傳輸,

          UDP用于對實時性要求的應(yīng)用。他是把大塊數(shù)據(jù)分成小的數(shù)據(jù)報,只發(fā)數(shù)據(jù)報,數(shù)據(jù)報自己負(fù)責(zé)尋址,所以不一定路徑一樣,順序可能亂。



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

          Untitled-1.jpg


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

          TCP/IP

          應(yīng)用層
          傳輸層
          網(wǎng)絡(luò)層
          網(wǎng)絡(luò)接口

          端口是一種抽象的軟件結(jié)構(gòu),與協(xié)議相關(guān)。

          TCP:23和UDP:23不相關(guān)。


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

          Socket是傳輸層的。網(wǎng)絡(luò)編程要注意在哪一個層次編程。

          基于TCP,java.net.ServerSocket,服務(wù)器進程。構(gòu)造函數(shù)一個端口號

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

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

          s和s1不同。

          獲得數(shù)據(jù),s.getInputStream(),s.getOutputStream()

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

          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;//默認(rèn)端口
            private static int online = 0;//當(dāng)前服務(wù)在線人數(shù)
            
            
          private List threadList;//客戶端連入Server后,啟動過的線程的集合,以便管理,群發(fā)
            final static PrintWriter sysout;//服務(wù)器本地輸出,無用,直接System.out,沒問題。
            
            
          static{
              sysout 
          = new PrintWriter(System.out,true);
            }

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

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

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

            }

            
            
          /**
            *
            * 私有成員內(nèi)部類(便于訪問外部類私有屬性),如果改為頂級類沒有問題,封裝了服務(wù)器與客戶端交換數(shù)據(jù)的獨立線程操作。
            
          */
            
            
          private class Transmit extends Thread{
              
          private BufferedReader input;//帶緩沖的字符流,作為輸入流,從中讀取發(fā)送到服務(wù)器的信息
              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,群發(fā)信息
                    }

                  }

                  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會關(guān)閉所打開的流,不要強行關(guān)閉流,會有問題。
                    }
          catch(Exception e){}
                }

              }

              
              
          //發(fā)送信息給其他線程所通訊的客戶端
              private void sendToOtherMsg(String ip,String msg)
                
          {
                  Iterator it 
          = threadList.iterator();
                  
          while(it.hasNext())
                  
          {
                      Transmit t 
          = ((Transmit)it.next());
                      
          if(!t.isAlive()) //如果線程已經(jīng)進入死亡狀態(tài),也就是線程已經(jīng)運行完畢,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連接
                
                
          //通過橋轉(zhuǎn)換,將socket得到的字節(jié)輸入流按照gb2312編碼方式轉(zhuǎn)換為字符輸入流,再封裝為帶緩沖的過濾流
                echo = new BufferedReader(new InputStreamReader(conn.getInputStream(),"gb2312"));
                
                
          //直接使用PrintWriter這個過濾流封裝字節(jié)輸出流為字符流,并帶有緩沖,比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)//服務(wù)器關(guān)閉
                  jta.append("Server down!\n");
                
          if(ex.getMessage().indexOf("Connection refused: connect")!=-1)//服務(wù)器不通
                  jta.append("connection refused!\nplease check network!\n");
              }

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

              
          finally
              
          {
                
          try{
                  conn.close();
          //只關(guān)閉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);//構(gòu)建帶滑動條的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);
          //右上角的叉子,生效,關(guān)閉窗體
              f.setVisible(true);//設(shè)置可見,否則不可見
              
              jtf.addActionListener(
          new ActionListener(){//添加事件處理
                public void actionPerformed(ActionEvent e){
                  String s
          =jtf.getText();
                  
          if(s.trim().equalsIgnoreCase("EXIT"))
                    done 
          = true;//讓主線程的while退出,進而結(jié)束Client
                  pw.println(s);//利用輸出流,輸出到服務(wù)器信息。
                  jtf.setText("");
                }

              }
          );
            }

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

          }


            

          UDP編程

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

          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上的端口沒關(guān)系,端口和協(xié)議有關(guān)。

          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(); 
                  
              }

          }

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

          Socket之間交換數(shù)據(jù)。

          交換DatagramPacket,內(nèi)容在字節(jié)數(shù)據(jù)中,發(fā)送方在Pocket寫上地址和端口,send。
          接收方必須準(zhǔn)備一個空信,以便接收內(nèi)容。received,將字節(jié)數(shù)組裝滿。

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

          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網(wǎng)絡(luò)編程 2006-07-02 10:56 | Sophia
          GG,謝謝哦,你的源程序救了我一命啊!!!!  回復(fù)  更多評論
            

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


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 北安市| 拜泉县| 西安市| 蓬溪县| 抚宁县| 吕梁市| 东辽县| 通辽市| 金寨县| 石家庄市| 太仆寺旗| 神池县| 灵台县| 资兴市| 山丹县| 肥城市| 舒兰市| 县级市| 金溪县| 巍山| 鄢陵县| 高雄县| 临朐县| 凭祥市| 太保市| 平泉县| 台州市| 佛山市| 沾益县| 岳普湖县| 仙居县| 桦川县| 云霄县| 乃东县| 苍溪县| 西林县| 长垣县| 翼城县| 乌恰县| 景洪市| 长乐市|