Java socket網絡編程

1,網絡基礎和軟件編程java

     軟件編寫人員不須要了解太多的網絡知識(基礎仍是須要的);軟件編寫人員主要抓住幾點就能夠作網絡編程;編程

        1,信息傳輸都是0和1的傳輸;瀏覽器

        2,信息傳輸須要遵守網絡協議;(底存的網絡協議   和傳輸格式協議)服務器

        3,抓住傳輸協議的要點(如  協議的用途   簡要協議實現方式)網絡

        4,IOapp

    注:有很軟件編程人員一般都不知道什麼是協議,抓不到協議重點;有些時候在對接的時候問他們使用的什麼協議,統一回復tcp/ip協議;這讓我非常蛋疼;dom

    補充:OSI(Open System Interconnection)開放式互聯協議模型
socket

                        分爲7層:1.物理層 2.數據鏈路層 3.網絡層 4.傳輸層 5.會話層 6.表示層 7.應用層jsp

             TCP/IP協議模型:
tcp

                        分爲4層: 1.網絡接口層,2.互聯網層 3.傳輸層 4.應用層

            協議都是分層的,咱們經常使用的都是應用層協議;如htpp協議;

            什麼是協議?協議規定了咱們在網絡傳輸中的格式樣板;

        

2,Java網絡編程Socket

   

1,什麼是Socket

網絡上的兩個程序經過一個雙向的通信鏈接實現數據的交換,這個雙向鏈路的一端稱爲一個SocketSocket一般用來實現客戶方和服務方的鏈接。SocketTCP/IP協議的一個十分流行的編程界面,一個Socket由一個IP地址和一個端口號惟一肯定。

可是,Socket所支持的協議種類也不光TCP/IP一種,所以二者之間是沒有必然聯繫的。在Java環境下,Socket編程主要是指基於TCP/IP協議的網絡編程。

2Socket通信的過程

ServerListen(監聽)某個端口是否有鏈接請求,Client端向Server 端發出Connect(鏈接)請求,Server端向Client端發回Accept(接受)消息。一個鏈接就創建起來了。Server端和Client 端均可以經過SendWrite等方法與對方通訊。

對於一個功能齊全的Socket,都要包含如下基本結構,其工做過程包含如下四個基本的步驟:

  (1 建立Socket

  (2 打開鏈接到Socket的輸入/出流;

  (3 按照必定的協議對Socket進行讀/寫操做;

  (4 關閉Socket.(在實際應用中,並未使用到顯示的close,雖然不少文章都推薦如此,不過在個人程序中,可能由於程序自己比較簡單,要求不高,因此並未形成什麼影響。)

3,建立Socket

建立Socket

java在包java.net中提供了兩個類SocketServerSocket,分別用來表示雙向鏈接的客戶端和服務端。這是兩個封裝得很是好的類,使用很方便。其構造方法以下:

  Socket(InetAddress address, int port);

  Socket(InetAddress address, int port, boolean stream);

  Socket(String host, int prot);

  Socket(String host, int prot, boolean stream);

  Socket(SocketImpl impl)

  Socket(String host, int port, InetAddress localAddr, int localPort)

  Socket(InetAddress address, int port, InetAddress localAddr, int localPort)

  ServerSocket(int port);

  ServerSocket(int port, int backlog);

  ServerSocket(int port, int backlog, InetAddress bindAddr)

  其中addresshostport分別是雙向鏈接中另外一方的IP地址、主機名和端 口號,stream指明socket是流socket仍是數據報socketlocalPort表示本地主機的端口號,localAddr bindAddr是本地機器的地址(ServerSocket的主機地址),implsocket的父類,既能夠用來建立serverSocket又可 以用來建立Socketcount則表示服務端所能支持的最大鏈接數。例如:學習視頻網 http://www.xxspw.com

  Socket client = new Socket("127.0.01.", 80);

  ServerSocket server = new ServerSocket(80);

  注意,在選擇端口時,必須當心。每個端口提供一種特定的服務,只有給出正確的端口,才 能得到相應的服務。0~1023的端口號爲系統所保留,例如http服務的端口號爲80,telnet服務的端口號爲21,ftp服務的端口號爲23, 因此咱們在選擇端口號時,最好選擇一個大於1023的數以防止發生衝突。

  在建立socket時若是發生錯誤,將產生IOException,在程序中必須對之做出處理。因此在建立SocketServerSocket是必須捕獲或拋出例外。

package com.dom.socket;

import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.ServerSocket;
import java.net.Socket;

public class ServiceDom {

    public static void main(String[] args){
        try {
            ServerSocket server = new ServerSocket(8082);
            Socket socket = server.accept();
            //得到服務端套接字的輸入輸出流
            Reader reader = new InputStreamReader(socket.getInputStream());  
              char chars[] = new char[64];  
              int len;  
              StringBuilder sb = new StringBuilder();  
              while ((len=reader.read(chars)) != -1) {  
                 sb.append(new String(chars, 0, len));  
              }  
              System.out.println("from client: " + sb);  
              reader.close();  
              socket.close();  
              server.close(); 
        } catch (IOException e) {
            e.printStackTrace();
        }
        
    }
    
}
package com.dom.socket;

import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.net.Socket;
import java.net.UnknownHostException;

public class ClientDom {

    public static void main(String [] ags){
        
        try {
            Socket socket = new Socket("127.0.0.1",8082);
            Writer writer = new OutputStreamWriter(socket.getOutputStream());
            writer.write("my socket dom");
            writer.flush();
            writer.close();  
            socket.close(); 

        } catch (UnknownHostException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
    }
}

    

使用socket實現http協議傳輸消息

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.ArrayList;

/**
 * 一個簡單的HTTP客戶端,發送HTTP請求,模擬瀏覽器
 * 可打印服務器發送過來的HTTP消息
 */
public class SimpleHttpClient {
    private static String encoding = "GBK";

    public static void main(String[] args) {
        try {
            Socket s = new Socket(InetAddress.getLocalHost(), 8080);
            OutputStreamWriter osw = new OutputStreamWriter(s.getOutputStream());
            StringBuffer sb = new StringBuffer();
            sb.append("GET /HttpStream/gb2312.jsp HTTP/1.1\r\n");
            sb.append("Host: localhost:8088\r\n");
            sb.append("Connection: Keep-Alive\r\n");
            sb.append("\r\n");
            osw.write(sb.toString());
            osw.flush();

            //--輸出服務器傳回的消息的頭信息
            InputStream is = s.getInputStream();
            String line = null;
            int contentLength = 0;//服務器發送回來的消息長度
            // 讀取全部服務器發送過來的請求參數頭部信息
            do {
                line = readLine(is, 0);
                //若是有Content-Length消息頭時取出
                if (line.startsWith("Content-Length")) {
                    contentLength = Integer.parseInt(line.split(":")[1].trim());
                }
                //打印請求部信息
                System.out.print(line);
                //若是遇到了一個單獨的回車換行,則表示請求頭結束
            } while (!line.equals("\r\n"));

            //--輸消息的體
            System.out.print(readLine(is, contentLength));

            //關閉流
            is.close();

        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /*
     * 這裏咱們本身模擬讀取一行,由於若是使用API中的BufferedReader時,它是讀取到一個回車換行後
     * 才返回,不然若是沒有讀取,則一直阻塞,直接服務器超時自動關閉爲止,若是此時還使用BufferedReader
     * 來讀時,由於讀到最後一行時,最後一行後不會有回車換行符,因此就會等待。若是使用服務器發送回來的
     * 消息頭裏的Content-Length來截取消息體,這樣就不會阻塞
     * 
     * contentLe 參數 若是爲0時,表示讀頭,讀時咱們仍是一行一行的返回;若是不爲0,表示讀消息體,
     * 時咱們根據消息體的長度來讀完消息體後,客戶端自動關閉流,這樣不用先到服務器超時來關閉。
     */
    private static String readLine(InputStream is, int contentLe) throws IOException {
        ArrayList lineByteList = new ArrayList();
        byte readByte;
        int total = 0;
        if (contentLe != 0) {
            do {
                readByte = (byte) is.read();
                lineByteList.add(Byte.valueOf(readByte));
                total++;
            } while (total < contentLe);//消息體讀還未讀完
        } else {
            do {
                readByte = (byte) is.read();
                lineByteList.add(Byte.valueOf(readByte));
            } while (readByte != 10);
        }

        byte[] tmpByteArr = new byte[lineByteList.size()];
        for (int i = 0; i < lineByteList.size(); i++) {
            tmpByteArr[i] = ((Byte) lineByteList.get(i)).byteValue();
        }
        lineByteList.clear();

        return new String(tmpByteArr, encoding);
    }
}

    上面都是採用的是io;由於NIO的緣故  這些代碼都不是本身寫的;後面準備本身寫NIO的實現;(就這一點東東就花了了我一天時間   真心傷不起呀;基礎   基礎  基礎夯實真的很重要)   在此記錄以備後用

相關文章
相關標籤/搜索