Java網(wǎng)絡(luò)編程

引言:網(wǎng)絡(luò)編程作為開發(fā)服務(wù)端和客戶端必不可少的技術(shù)之一陆馁,在Java中也實(shí)現(xiàn)的十分完備,今天對(duì)Java的網(wǎng)絡(luò)編程方面的只是做一個(gè)簡(jiǎn)單的總結(jié)合愈,方便以后學(xué)習(xí):

一:什么是網(wǎng)絡(luò)編程叮贩?

  • 1:概念:通過(guò)使用套接字來(lái)達(dá)到進(jìn)程間通信目的的編程就是網(wǎng)絡(luò)編程。windows提供的基于網(wǎng)絡(luò)編程的就是套接字也就是winsock佛析,同時(shí)Winpcap也是一個(gè)比較方便的工具妇汗。

  • 2:幾個(gè)常用概念:

  • 網(wǎng)絡(luò)模型:描述網(wǎng)絡(luò)的結(jié)構(gòu)原理和工作原

  • OSI參考模型:七層

  • Internet網(wǎng)絡(luò)模型:四層

  • 網(wǎng)絡(luò)協(xié)議:指定層上進(jìn)行數(shù)據(jù)交換的規(guī)則。

  • Internet的網(wǎng)絡(luò)層協(xié)議:IP協(xié)議说莫;DNS協(xié)議(輔助協(xié)議)

  • Internet的傳輸層協(xié)議:TCP協(xié)議,UDP協(xié)議

  • 3:Java的Socket通信模型:

通訊模型.png

相關(guān)類介紹:

  • A:ServerSocket:用java.net.ServerSocket實(shí)現(xiàn)java服務(wù)通過(guò)TCP/IP監(jiān)聽客戶端連接‘寞焙;
    創(chuàng)建監(jiān)聽指定端口號(hào):
ServerSocket serverSocket = new ServerSocket(9000);

要獲取請(qǐng)求的連接需要用ServerSocket.accept()方法储狭。該方法返回一個(gè)Socket類,該類具有普通java Socket類的所有特性捣郊。每個(gè)調(diào)用了accept()方法的ServerSocket都只獲得一個(gè)連接辽狈;

Socket socket = ServerSocket.accept();
  • B:Socket:當(dāng)我們想要在Java中使用TCP/IP通過(guò)網(wǎng)絡(luò)連接到服務(wù)器時(shí),就需要?jiǎng)?chuàng)建java.net.Socket對(duì)象并連接到服務(wù)器
    創(chuàng)建連接到指定地址和端口的Socket;
Socket socket = new Socket("78.46.84.171", 80);

通過(guò)Socket發(fā)送數(shù)據(jù):

OutputStream out = socket.getOutputStream(); 
out.write("some data".getBytes());
out.flush();
out.close(); 

不要忘記調(diào)用輸出流的flush()方法呛牲;操作系統(tǒng)底層的TCP/IP實(shí)現(xiàn)會(huì)先將數(shù)據(jù)放入一個(gè)更大的數(shù)據(jù)緩存塊中刮萌,而緩存塊的大小是與TCP/IP的數(shù)據(jù)包大小相適應(yīng)的。(譯者注:調(diào)用flush()方法只是將數(shù)據(jù)寫入操作系統(tǒng)緩存中娘扩,并不保證數(shù)據(jù)會(huì)立即發(fā)送)
通過(guò)Socket讀取數(shù)據(jù)

InputStream in = socket.getInputStream(); 
int data = in.read();

需要注意的是着茸,從Socket的輸入流中讀取數(shù)據(jù)并不能讀取文件那樣,一直調(diào)用read()方法直到返回-1為止琐旁,因?yàn)閷?duì)Socket而言涮阔,只有當(dāng)服務(wù)端關(guān)閉連接時(shí),Socket的輸入流才會(huì)返回-1灰殴,而是事實(shí)上服務(wù)器并不會(huì)不停地關(guān)閉連接敬特。假設(shè)我們想要通過(guò)一個(gè)連接發(fā)送多個(gè)請(qǐng)求,那么在這種情況下關(guān)閉連接就顯得非常愚蠢牺陶。
因此伟阔,從Socket的輸入流中讀取數(shù)據(jù)時(shí)我們必須要知道需要讀取的字節(jié)數(shù),這可以通過(guò)讓服務(wù)器在數(shù)據(jù)中告知發(fā)送了多少字節(jié)來(lái)實(shí)現(xiàn)掰伸,也可以采用在數(shù)據(jù)末尾設(shè)置特殊字符標(biāo)記的方式連實(shí)現(xiàn)皱炉。

  • C:URL和URLConnection類
    在java.net包中包含兩個(gè)有趣的類:URL類和URLConnection類。這兩個(gè)類可以用來(lái)創(chuàng)建客戶端到web服務(wù)器(HTTP服務(wù)器)的連接碱工,當(dāng)然也可建立客戶端可本地文件之間的連接娃承,
URL url = new URL("http://jenkov.com");創(chuàng)建一個(gè)到到改地址的URL
URLConnection urlConnection = url.openConnection()
InputStream input = urlConnection.getInputStream();
int data = input.read();
while(data != -1){
    System.out.print((char) data);
    data = input.read();
}
 input.close();
  • D:InetAddress類:是 Java 對(duì) IP 地址的封裝奏夫。里面包含了很多關(guān)于ID地址的信息;這個(gè)類的實(shí)例經(jīng)常和 UDP DatagramSockets 和 Socket历筝,ServerSocket 類一起使用酗昼。
  • E:DatagramSocket代表UDP協(xié)議的Socket,DatagramSocket本身只是碼頭梳猪,不維護(hù)狀態(tài)麻削,不能產(chǎn)生IO流,它的唯一作用就是接收和發(fā)送數(shù)據(jù)報(bào)春弥,Java使用DatagramPacket來(lái)代表數(shù)據(jù)報(bào)呛哟,DatagramSocket接收和發(fā)送的數(shù)據(jù)都是通過(guò)DatagramPacket對(duì)象完成的。
  • DatagramPacket:基于UDP的數(shù)據(jù)包類匿沛,里面可以填寫很多信息扫责,地址,端口逃呼,數(shù)據(jù)等鳖孤;
    .由這兩個(gè)類所有構(gòu)成的網(wǎng)絡(luò)鏈接是基于UDP協(xié)議,是一種不可靠的協(xié)議抡笼。

二:具體代碼實(shí)現(xiàn):

1:基于TCP的客服端和服務(wù)端通信:
服務(wù)端代碼:

public class Server {
    public static void main(String[] args) {
        try {
            //創(chuàng)建一個(gè)服務(wù)端監(jiān)聽8888端口
            ServerSocket server = new ServerSocket(8888);
            //調(diào)用accept方法開始監(jiān)聽苏揣,等待客戶端建立連接
            System.out.println("服務(wù)段開始監(jiān)聽...............");
            Socket socket = server.accept();
            InputStream in  = socket.getInputStream();
            InputStreamReader reader = new InputStreamReader(in);
            BufferedReader buff = new BufferedReader(reader);
        
            String line=null;
            while((line=buff.readLine())!=null){
                System.out.println("我是服務(wù)端:客戶端說(shuō):"+line);
            }
            socket.shutdownInput();
            OutputStream out = socket.getOutputStream();
            PrintWriter rw = new PrintWriter(out);
            rw.write("你好客戶端呀!M埔觥F叫佟!");
            rw.close();
            buff.close();
            reader.close();
            in.close();
            server.close();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

客戶端代碼:

public class Client {
    public static void main(String[] args) {
              try {
            Socket client = new Socket("127.0.0.1",8888);
            OutputStream out = client.getOutputStream();
            PrintWriter pw = new PrintWriter(out);
            pw.write("用戶名:admin;密碼:123");
            pw.flush();
            //記住關(guān)閉
            client.shutdownOutput();
                /**
                 * 讀取服務(wù)端發(fā)送來(lái)的信息
                 */
                InputStream in = client.getInputStream();
                InputStreamReader reader = new InputStreamReader(in);
                BufferedReader buf = new BufferedReader(reader);
                int data = buf.read();
                while(data!=-1){
                    System.out.print((char)data);
                    data=buf.read();
                }
                buf.close();
                reader.close();
                in.close();
            pw.close();
            out.close();
            client.close();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

2:基于UDP的客服端和服務(wù)端連接:
服務(wù)端:

public class Server {
    public static void main(String[] args) throws IOException {
        try {
            //1:創(chuàng)建服務(wù)的端的Socket并指定端口
            DatagramSocket socket = new DatagramSocket(8800);
            byte[] arr = new byte[1024];
            DatagramPacket packet = new DatagramPacket(arr, arr.length);
            System.out.println("服務(wù)端已經(jīng)打開了:");
            socket.receive(packet);
            String str = new String(arr);
            System.out.println(str);    
            //1:向客戶端發(fā)送信息時(shí)藏古,也需要知道客戶端的地址端口號(hào)等信息
                InetAddress address = packet.getAddress();
                int port1 = packet.getPort();
                System.out.println(port1+"==============");
                byte[] arr1 = "歡迎您".getBytes();
                DatagramPacket datapacketR = new DatagramPacket(arr1,arr1.length,address,port1);
                socket.send(datapacketR);
                  socket.shutdown();
        } catch (SocketException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

客戶端:

public class Client {
    public static void main(String[] args) throws IOException {
        //1:創(chuàng)建服務(wù)的端的地址增炭,并定義端口號(hào),并定義數(shù)據(jù)
        InetAddress inetAddress = InetAddress.getByName("localhost");
        int port = 8800;
        byte[] bytes = "用戶名:陳鵬拧晕,密碼:1234".getBytes();
        //2:創(chuàng)建數(shù)據(jù)報(bào)弟跑,包含發(fā)送的地址信息
        DatagramPacket datapacket = new DatagramPacket(bytes, bytes.length,inetAddress,port);
        //3:創(chuàng)建Socket
        DatagramSocket socket = new DatagramSocket();
        socket.send(datapacket);
        //接受服務(wù)端發(fā)送來(lái)的信息
        byte[] arr = new byte[1024];
            DatagramPacket datapacketR = new DatagramPacket(arr,arr.length);
            socket.receive(datapacketR);
            String data = new String(arr);
            System.out.println("我是客戶端,服務(wù)器端響應(yīng)的數(shù)據(jù)是:"+data);    
    }
}

三:自定協(xié)議:

需要考慮三點(diǎn):

  • 1:客戶端到服務(wù)端的往返通訊
  • 1.在分開往返中發(fā)送頭信息防症;
  • 2.將消息分成更小的數(shù)據(jù)塊孟辑。
  • 2:區(qū)分請(qǐng)求結(jié)束和響應(yīng)結(jié)束。
    • 1:在請(qǐng)求頭中包含請(qǐng)求信息長(zhǎng)度
    • 2:在請(qǐng)求體中增加標(biāo)志位
  • 3:防火墻穿透
  • 1:基于HTTP協(xié)議上建立協(xié)議蔫敲;
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末饲嗽,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子奈嘿,更是在濱河造成了極大的恐慌貌虾,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,591評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件裙犹,死亡現(xiàn)場(chǎng)離奇詭異尽狠,居然都是意外死亡衔憨,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,448評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門袄膏,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)践图,“玉大人,你說(shuō)我怎么就攤上這事沉馆÷氲常” “怎么了?”我有些...
    開封第一講書人閱讀 162,823評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵斥黑,是天一觀的道長(zhǎng)揖盘。 經(jīng)常有香客問我,道長(zhǎng)锌奴,這世上最難降的妖魔是什么兽狭? 我笑而不...
    開封第一講書人閱讀 58,204評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮鹿蜀,結(jié)果婚禮上椭符,老公的妹妹穿的比我還像新娘。我一直安慰自己耻姥,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,228評(píng)論 6 388
  • 文/花漫 我一把揭開白布有咨。 她就那樣靜靜地躺著琐簇,像睡著了一般。 火紅的嫁衣襯著肌膚如雪座享。 梳的紋絲不亂的頭發(fā)上婉商,一...
    開封第一講書人閱讀 51,190評(píng)論 1 299
  • 那天,我揣著相機(jī)與錄音渣叛,去河邊找鬼丈秩。 笑死,一個(gè)胖子當(dāng)著我的面吹牛淳衙,可吹牛的內(nèi)容都是我干的蘑秽。 我是一名探鬼主播,決...
    沈念sama閱讀 40,078評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼箫攀,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼肠牲!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起靴跛,我...
    開封第一講書人閱讀 38,923評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤缀雳,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后梢睛,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體肥印,經(jīng)...
    沈念sama閱讀 45,334評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡识椰,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,550評(píng)論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了深碱。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片腹鹉。...
    茶點(diǎn)故事閱讀 39,727評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖莹痢,靈堂內(nèi)的尸體忽然破棺而出种蘸,到底是詐尸還是另有隱情,我是刑警寧澤竞膳,帶...
    沈念sama閱讀 35,428評(píng)論 5 343
  • 正文 年R本政府宣布航瞭,位于F島的核電站,受9級(jí)特大地震影響坦辟,放射性物質(zhì)發(fā)生泄漏刊侯。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,022評(píng)論 3 326
  • 文/蒙蒙 一锉走、第九天 我趴在偏房一處隱蔽的房頂上張望滨彻。 院中可真熱鬧,春花似錦挪蹭、人聲如沸亭饵。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,672評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)辜羊。三九已至,卻和暖如春词顾,著一層夾襖步出監(jiān)牢的瞬間八秃,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,826評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工肉盹, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留昔驱,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,734評(píng)論 2 368
  • 正文 我出身青樓上忍,卻偏偏與公主長(zhǎng)得像骤肛,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子窍蓝,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,619評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容