电竞比分网-中国电竞赛事及体育赛事平台

分享

java網(wǎng)絡(luò)學(xué)習(xí)筆記

 ShangShujie 2007-07-19
1.Java與網(wǎng)絡(luò)
* 網(wǎng)絡(luò)是java取得成功的領(lǐng)域之一
* (其他語言)數(shù)頁(yè)代碼---->(Java)一條語句
* 在java中有一個(gè)用來存儲(chǔ) internet 地址的類 InetAddress
例子://獲取本機(jī)IP地址,創(chuàng)建 InetAddress 不用 new

import java.net.*;
public class GetLocalHost{
public static void main(String args[]){
InetAddress myIP=null;
try{
myIP=InetAddress.getLocalHost();
System.out.println(myIP);
}catch(Exception e){
e.printStackTrace();
}
}
}


* java提供的網(wǎng)絡(luò)功能有3大類:
a. URL
通過URL可以直接送出或讀入網(wǎng)絡(luò)上的數(shù)據(jù)
b. socket
傳統(tǒng)網(wǎng)絡(luò)程序的最常用方式,可以想象為兩個(gè)程序通過網(wǎng)絡(luò)的通信信道
c. Datagram
更低級(jí)的網(wǎng)絡(luò)傳輸方式,他把數(shù)據(jù)的目的地記錄在數(shù)據(jù)包中,直接放在網(wǎng)上
2. OSI 模型和 TCP/IP 協(xié)議棧
* OSI 模型從下到上依次為:
(1)物理層 規(guī)定電氣特性
(2)數(shù)據(jù)鏈路層 保證相臨兩臺(tái)計(jì)算機(jī)傳輸,用物理地址(網(wǎng)卡地址 )做網(wǎng)絡(luò)標(biāo)識(shí),主要設(shè)備 hub
(3)網(wǎng)絡(luò)層 實(shí)現(xiàn)跨網(wǎng)段傳輸,用 IP 做標(biāo)識(shí),主要設(shè)備 router, 協(xié)議 IP
(4)傳輸層 保證無差錯(cuò)傳輸,協(xié)議 TCP,每個(gè)包都有syn號(hào)和效驗(yàn)碼,傳輸前后的效驗(yàn)碼比較,相同為正確,不同為錯(cuò)誤,重傳
這一層承上啟下,出現(xiàn)了端口概念:用來區(qū)分不同的應(yīng)用,范圍 0--65535,0--1024一般不要用,是系統(tǒng)保留號(hào)
(5)會(huì)話層 如身份驗(yàn)證
(6)表現(xiàn)層
(7)應(yīng)用層 Http,Ftp......
* TCP/IP 協(xié)議棧把OSI 模型合為四層
(1)鏈路層(物理層,數(shù)據(jù)鏈路層)
(2)網(wǎng)絡(luò)層 IP,ICMP,ARP,RARP...
(3)傳輸層 TCP,UDP...
(4)應(yīng)用層 (會(huì)話層,表現(xiàn)層,應(yīng)用層) HTTP,F(xiàn)TP,TELNET,POP3,SMPT...
3.Socket
* Socket 是網(wǎng)絡(luò)上運(yùn)行的程序之間雙向通信連路的最后終結(jié)點(diǎn)
* IP 與 端口 的組合得出一個(gè)套接字,可以完全分辨internet上的程序
* 端口號(hào):TCP/IP 為每種程序定義了一個(gè)端口號(hào),當(dāng)一臺(tái)計(jì)算機(jī)上運(yùn)行不同程序時(shí),根據(jù)端口號(hào)不同提供響應(yīng)服務(wù)
端口號(hào)不是計(jì)算機(jī)上的物理連接器,只是具有軟件意義的假想端口
* 常用端口號(hào):
ftp: 21 http: 80 telnet: 23 nntp: 119 dns: 53 pop3: 110
* 在服務(wù)器端通過指定一個(gè)用來等待連接的端口號(hào)創(chuàng)建 ServerSocket 實(shí)例
* 在客戶端通過規(guī)定一個(gè)主機(jī)和端口號(hào)創(chuàng)建 Socket 實(shí)例,連接到服務(wù)器
* 寫一個(gè) SocketServer 的步驟:
(1)創(chuàng)建一個(gè)ServerSocket對(duì)象
(2)調(diào)用 accept(),從客戶端接受一個(gè)連接請(qǐng)求并返回一個(gè)新 socket
accept()是個(gè)阻塞方法,使 Server 啟動(dòng),等待請(qǐng)求,開始監(jiān)聽
(3)從接受的socket中得到輸入/輸出流
(4)根據(jù)數(shù)據(jù)類型封裝高級(jí)流(可選)
(5)收發(fā)信息
(6)釋放資源
* 寫一個(gè) socket 客戶端的步驟:
(1)創(chuàng)建一個(gè) socket,向 Server發(fā)請(qǐng)求得到一個(gè)連接
(2)得到輸入/輸出流
(3)根據(jù)數(shù)據(jù)類型封裝高級(jí)流(可選)
(4)收發(fā)信息
(5)釋放資源
例子:
//server 讀取 client 發(fā)來的數(shù)據(jù)顯示出來,直到收到 "bye" 結(jié)束
//先打開一個(gè)命令行窗口運(yùn)行 Server,然后再開一個(gè)運(yùn)行 Client

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

public class Server{
public static void main(String args[]){
ServerSocket ss=null;
Socket s=null;
BufferedReader br=null;
String read=null;
try{
ss=new ServerSocket(1111);
System.out.println("Server is listening on 1111......");
s=ss.accept();
br=new BufferedReader(new InputStreamReader(s.getInputStream()));
while(true){
read=br.readLine();
System.out.println(
"read=>"+read);
if(read.equals(
"bye")) break;
}
}catch(Exception e){
e.printStackTrace();
}finally{
try{
if(br!=null) br.close();
if(s!=null) s.close();
if(ss!=null) ss.close();
System.out.println(
"Connection is closed");
}catch(Exception e){
e.printStackTrace();
}
}
}
//client 接收客戶輸入向server 發(fā)出,直到用戶輸入 "bye" 結(jié)束
import java.io.*;
import java.net.*;

public class Server{
public static void main(String args[]){
ServerSocket ss=null;
Socket s=null;
BufferedReader br=null;
String read=null;
try{
ss=new ServerSocket(1111);
System.out.println(
"Server is listening on 1111......");
s=ss.accept();
br=new BufferedReader(new InputStreamReader(s.getInputStream()));
while(true){
read=br.readLine();
System.out.println(
"read=>"+read);
if(read.equals(
"bye")) break;
}
}catch(Exception e){
e.printStackTrace();
}finally{
try{
if(br!=null) br.close();
if(s!=null) s.close();
if(ss!=null) ss.close();
System.out.println(
"Connection is closed");
}catch(Exception e){
e.printStackTrace();
}
}
}
}
}


* 上面的例子 client 一結(jié)束 server 也結(jié)束了,這太不實(shí)際了,下面做一個(gè)可以處理多用戶的 server
這就需要多線程,server接到一個(gè)用戶的請(qǐng)求就創(chuàng)建一個(gè)線程處理他
例子:
//多線程處理多請(qǐng)求,多開幾個(gè)窗口試一下
import java.io.*;
import java.net.*;

public class Server{
public static void main(String args[]){
ServerSocket ss=null;
Socket s=null;
BufferedReader br=null;
String read=null;
try{
ss=new ServerSocket(1111);
System.out.println(
"Server is listening on 1111......");

//br=new BufferedReader(new InputStreamReader(s.getInputStream()));
while(true){
s=ss.accept();
Thread t=new NewServer(s);
t.start();
}
}catch(Exception e){
e.printStackTrace();
}finally{
try{
if(br!=null) br.close();
if(s!=null) s.close();
if(ss!=null) ss.close();
System.out.println(
"Connection is closed");
}catch(Exception e){
e.printStackTrace();
}
}
}
}
class NewServer extends Thread{
BufferedReader br=null;
String read=null;
Socket s=null;
public NewServer(Socket s){
this.s=s;
}
public void run(){
try{
br=new BufferedReader(new InputStreamReader(s.getInputStream()));
while(true){
read=br.readLine();
System.out.println(getName()+
" read=>"+read);
if(read.equals(
"bye")) break;
}
System.out.println(getName() +
" connection is closed");
}catch(Exception e){
e.printStackTrace();
}finally{
if(br!=null) try{ br.close();} catch(Exception e){ e.printStackTrace(); }
if(s!=null) try{ s.close(); } catch(Exception e){ e.printStackTrace(); }
}
}
}

* 下面來做一個(gè)雙向交互的例子,簡(jiǎn)單的用戶名驗(yàn)證,接受用戶輸入的用戶名,直到輸入“java"為止
例子:
import java.io.*;
import java.net.*;

public class LoginServer{
public static void main(String[] args){
ServerSocket ss=null;
Socket s=null;
BufferedReader br=null;
PrintWriter pw=null;
String line=null;
String username=
"java";
try{
ss=new ServerSocket(1111);
System.out.println(
"Server is listening on 1111......");
s=ss.accept();
pw=new PrintWriter(
new OutputStreamWriter(s.getOutputStream()));
br=new BufferedReader(
new InputStreamReader(s.getInputStream()));

while(true){
pw.println(
"login:");
pw.flush();
line=br.readLine();
System.out.println(line);
if(line.equals(username)) {
pw.println(
"login sucessful");
pw.flush();
break;
}
pw.println(
"wrong name");
pw.flush();
line=null;
}

}catch(Exception e){
e.printStackTrace();
}finally{
if(pw!=null) try{ pw.close(); }catch(Exception e){ e.getMessage(); }
if(br!=null) try{ br.close(); } catch(Exception e){ e.getMessage(); }
if(s!=null) try{ s.close(); } catch(Exception e){ e.getMessage(); }
if(ss!=null) try{ ss.close(); } catch(Exception e){ e.getMessage(); }
}
}
}

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

public class LoginClient{
public static void main(String[] args){
Socket s=null;
BufferedReader br=null,input;
PrintWriter pw=null;
String line=null;
String r=null,t=null;
try{
s=new Socket(
"127.0.0.1",1111);
br=new BufferedReader(
new InputStreamReader(s.getInputStream()));
input=new BufferedReader(
new InputStreamReader(System.in));
pw=new PrintWriter(
new OutputStreamWriter(s.getOutputStream()));


while(true){
line= br.readLine();
System.out.print(line);
r=input.readLine();
pw.println(r);
pw.flush();
t=br.readLine();
System.out.println(t);
if(t.equals(
"login sucessful")) break;
line=null;
}
}catch(Exception e){
e.printStackTrace();
}finally{
if(pw!=null) try{ pw.close(); } catch(Exception e){ e.printStackTrace(); }
if(br!=null) try{ br.close(); } catch(Exception e) { e.printStackTrace(); }
if(s!=null) try{ s.close(); } catch(Exception e){ e.getMessage(); }

}
}
}


4. UDP
* UDP 為無連接協(xié)議,不可靠傳輸。DatagramSocket 和 DatagramPacket 支持 Java UDP
* 數(shù)據(jù)報(bào)是一個(gè)網(wǎng)絡(luò)上發(fā)送的單獨(dú)信息,他到達(dá)的時(shí)間和內(nèi)容不能得到保證
* TCP 提供高可靠服務(wù),適用于一次傳送交換大量報(bào)文 的情況,信道上包不需要源地址和目的地址
UDP提供高效率服務(wù),適用于依次傳輸交換少量報(bào)文的情況,每個(gè)包要包含目的地址和端口號(hào)
* 數(shù)據(jù)報(bào)文的使用以包為中心:打包,拆包
* 寫 UDP Server 的步驟:
(1)創(chuàng)建一個(gè)綁定端口的 datagram DatagramSocket(port)
(2)準(zhǔn)備一個(gè)DatagramPacket接受客戶端的信息 DatagramPacket(buffer,len)
(3)從DatagramSocket接收信息放入 DatagramPacket
(4)讀取信息
* 寫 UDP Client 的步驟:
(1)創(chuàng)建一個(gè) datagram socket DatagramSocket()
(2)準(zhǔn)備一個(gè)包含信息和服務(wù)器協(xié)議地址信息的datagram packet DatagramPacket(buffer,len,Serveraddr,serverport)
(3)從datagram socket 把datagram packet發(fā)送到server
例子:
import java.net.*;
public class UDPServer{
public static void main(String[] args){
DatagramSocket ds=null;
DatagramPacket dp=null;
byte buf[]=new byte[1024];
try{
ds=new DatagramSocket(1111);
dp=new DatagramPacket(buf,buf.length);
System.out.println(
"begin recieve......");
ds.receive(dp);
String s=new String(dp.getData(),0,dp.getLength());
System.out.println(
"read=>"+s);
System.out.println(
"address:"+dp.getAddress());
System.out.println(
"socket address:"+dp.getSocketAddress());
System.out.println(
"port:"+dp.getPort());
}catch(Exception e){
e.printStackTrace();
}finally{
if( ds != null ) try{ ds.close(); } catch( Exception e ){}
}
}
}

import java.net.*;
public class UdpC{
public static void main(String[] args){
DatagramSocket ds=null;
DatagramPacket dp=null;
byte buf[]=
"hello world".getBytes();
try{
ds=new DatagramSocket();
dp=new DatagramPacket(buf,buf.length,InetAddress.getLocalHost(),1111);
ds.send(dp);
}catch(Exception e){
e.printStackTrace();
}finally{
if(ds!=null) try{ ds.close(); }catch(Exception e){ e.printStackTrace(); }
}
}
}


5.小結(jié)
* 網(wǎng)絡(luò)上的數(shù)據(jù)傳輸是將網(wǎng)絡(luò)連接轉(zhuǎn)換成輸入輸出流
* Socket適用于面向連接的,高可靠的應(yīng)用
* Socket是由IP和端口構(gòu)成的一種網(wǎng)上通信連路的一端
* UDP適用效率高的應(yīng)用
* Socket server/client 的編程步驟
* UDP server/client 的編程步驟

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多