java 網路程式設計(Socket) TCP/UDP 總結案例
網路程式設計:關注的是底層的資料傳輸
網頁程式設計:資料的展示
1、基本概念
一、網路:將不同的計算機連線在一起區域網 都會網路 網際網路
二、地址:Ip地址確定網路上的絕對的地址位置 房子的地址
三、埠號(相當於房門):區分計算機上的軟體 相當於房門兩個位元組0~65535 共65536個
1、 同一個協議下,埠號不能重複,不同的協議下可以重複
2、 1024以下的埠不要使用 80-->http 21-->ftp
四、資源定位 URL 統一資源定位 URI:統一資源
五、資料的傳輸
1、 協議:TCP和 UDP協議(重點的)
1)、TCP(transfer control protocol):必須先建立連線 先連線在通訊 電話 類似於三次握手 面向連線 安全可靠 效率相對低下
2)、UDP(UserDatagramProtocol):類似於發簡訊 非面向連線 效率高
現在一般是將兩者結合使用,底層一些不重要的資料使用UDP傳輸
2、 傳輸
1、 先封裝
2、 後拆分
3、資料封裝拆分
1、 InetAddress InetSocketAddress
2、 URL
3、 TCP:serverSocket(建立在伺服器上) Socket(建立在客戶端上)
4、 UDP: DatagramSocket DatagramPacket
1、InetAddress:封裝IP及DNS
方法:
getHostAddress() 返回ip地址
getHostName() 返回域名|本機為計算機名
InetAddress.getLocalHost();//本機
InetAddress.getByName(“IP地址|域名”);
2、InetSocketAddress:封裝埠
1):建立物件:
InetSocketAddress(String hostname,int port)
InetSocketAddress(InetAddress addr,intport)
2):方法:
getAdddress()
getHostName()
getPort()
<span style="font-size:18px;">package com.net.ip; import java.net.InetAddress; import java.net.UnknownHostException; /** * 沒有封裝埠 * @author lyy * */ public class InetDemo1 { public static void main(String[] args) throws UnknownHostException { //使用getLoaclHost方法建立InetAddress物件 InetAddress addr = InetAddress.getLocalHost(); System.out.println(addr.getHostAddress());//返回ip地址 System.out.println(addr.getHostName());//輸入計算機名 //根據域名得到InetAddress物件 addr = InetAddress.getByName("www.163.com"); System.out.println(addr.getHostAddress());//返回伺服器的ip地址61.163.117.65 System.out.println(addr.getHostName()); //輸出 www.163.com //根據ip得到InetAddress物件 addr = InetAddress.getByName("61.163.117.65");//如果ip地址存在而且DNS幫你解析了,那麼getHostName()這個方法返回的就是www.163.com ,否則輸出Ip地址 System.out.println(addr.getHostAddress());//返回163的伺服器的ip System.out.println(addr.getHostName());//輸入Ip而不是域名,如果這個Ip地址不存在 } </span> }
<span style="font-size:18px;">package com.net.ip;
import java.net.*;
/**
* 封裝埠:在InetAddress基礎上+埠
* @author lyy
*
*/
public class InetSocketDemo1 {
public static void main(String[] args) throws UnknownHostException {
InetSocketAddress address = new InetSocketAddress("127.0.0.1", 9999);
address= new InetSocketAddress(InetAddress.getByName("127.0.0.1"), 9999);
System.out.println(address.getHostName());
System.out.println(address.getPort());
InetAddress addr = address.getAddress();
System.out.println(addr.getHostAddress());//返回ip地址
System.out.println(addr.getHostName());//輸入計算機名
}
}</span>
3、網路爬蟲原理
URI(Uniform resource identifier) 統一資源識別符號,用唯一的標識一個資源
URL(Uniform resource Locator)統一資源定位器,他是一種具體的URI
四部分組成:協議存放資源的主機域名埠 資原始檔名(/)
URL:
一、建立
URI(URL context,
String spec)//
相對路徑構建
二、方法:
System.out.println("協議:"+url.getProtocol());
System.out.println("域名:"+url.getHost());
System.out.println("埠:"+url.getPort());
System.out.println("資源:"+url.getFile());
System.out.println("相對路徑資源:"+url.getPath());
System.out.println("錨點:"+url.getRef());//錨點
System.out.println("引數:"+url.getQuery());//引數:存在錨點回返Null 如果不存在返回引數
<span style="font-size:18px;">package com.net.url;
import java.net.*;
public class URLDemo1 {
public static void main(String[] args) throws MalformedURLException {
//絕對路徑構建
URL url = new URL("http://www.baidu.com:80/index.html#aa?uname=lyy");
System.out.println("協議:"+url.getProtocol());
System.out.println("域名:"+url.getHost());
System.out.println("埠:"+url.getPort());
System.out.println("資源:"+url.getFile());
System.out.println("相對路徑資源:"+url.getPath());
System.out.println("錨點:"+url.getRef());//錨點
System.out.println("引數:"+url.getQuery());//引數 :存在錨點 返回Null 如果不存在返回引數
//相對路徑構建
url = new URL("http://www.baidu.com:80/a/");
url = new URL(url,"b.txt");//相對路徑
System.out.println(url.toString());
}
}<strong>
</strong></span>
4、通過流讀取資料——OpenStream()
package com.net.url;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.*;
/**
* 獲取資源:原始碼
* @author lyy
*
*/
public class URLDemo2 {
public static void main(String[] args) throws IOException {
URL url = new URL("http://www.baidu.com/");//主頁預設資源
//獲取資源 網路流
// InputStream is = url.openStream();
// byte[] flush = new byte[1024];
// int len = 0;
// while(-1 != (len = is.read(flush))){
// System.out.println(new String(flush,0,len));
// }
// is.close();
BufferedReader br =
new BufferedReader(new InputStreamReader(url.openStream(),"utf-8"));
BufferedWriter bw =
new BufferedWriter(new OutputStreamWriter(new FileOutputStream("baidu.html"),"utf-8"));
String msg = null;
while((msg = br.readLine()) != null){
bw.append(msg);
bw.newLine();
}
bw.flush();
br.close();
bw.close();
}
}
5、UDP通訊
UDP:以資料為中心 非面向連線 不安全 資料可能丟失 效率高
一、類 DatagramSocketDatagramPacket
1、 客戶端:
1)、建立客戶端DatagramSocket 類 +指定埠
2)、準備資料位元組陣列
3)、打包 datagramPacket + 伺服器地址和埠
4)、傳送
5)、釋放資源
2、 服務端
a) 建立服務端 DatagramSocket類 +指定埠
b) 準備接收的容器位元組陣列 封裝datagramPacket
c) 包接收資料
d) 分析資料
e) 釋放資源
典型的b/s 先從伺服器下載源到瀏覽器(客戶端)
<span style="font-size:18px;">package com.net.udp;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
/**
* 服務端
* 1 建立服務端 + 埠
* 2 準備接收容器
* 3 封裝成包
* 4 接收資料
* 5 分析資料
* @author lyy
*
*/
public class MyServer {
public static void main(String[] args) throws IOException {
// 1 建立服務端 + 埠
DatagramSocket server = new DatagramSocket(8888);
// 2 準備接收容器
byte[] container = new byte[1024];
// 3 封裝成包 DatagramPacket(byte[] buf, int length)
DatagramPacket packet = new DatagramPacket(container, container.length);
// 4 接收資料
server.receive(packet);
// 5 分析資料
byte[] data = packet.getData();
int len = packet.getLength();
System.out.println(new String(data,0,len));
//釋放資源
server.close();
}
}</span>
<span style="font-size:18px;">package com.net.udp;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
/**
* 客戶端
* 1 建立客戶端 + 埠
* 2 準備資料
* 3 打包(傳送的地點 以及埠)
* 4 傳送
* 5 釋放
*
* @author lyy
*
*/
public class MyClient {
public static void main(String[] args) throws IOException {
// 1 建立客戶端 + 埠
DatagramSocket client = new DatagramSocket(6666);
// 2 準備資料
String msg = "真的愛你";
byte[] data = msg.getBytes();
// 3 打包(傳送的地點 以及埠) DatagramPacket(byte[] buf, int length, InetAddress address, int port)
DatagramPacket packet = new DatagramPacket(data, data.length,new InetSocketAddress("localhost",8888));
// 4 傳送
client.send(packet);
// 5 釋放
client.close();
}
}
</span>
6、Scoket通訊基於TCP:面向連線安全 可靠 效率低 類似於打電話
一、面向連線:請求 響應 Request——Response
二、Socket 程式設計
1、伺服器ServerSocket
2、客戶端 Socket
package com.net.tcp.socket;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
/**
* 必須先啟動伺服器 後連線
* 1 建立伺服器 指定埠
* 2 接收客戶端連線
* 3 傳送資料和接收資料
*
* 接收多個客戶端
* @author lyy
*
*/
public class MultServer {
public static void main(String[] args) throws IOException {
//1 建立服務區 指定埠 ServerSocket(int port)
ServerSocket server = new ServerSocket(8888);
// 2 接收客戶端連線 阻塞式
while(true){//死迴圈 一個accept() 一個客戶端
Socket socket = server.accept();
System.out.println("一個客戶端建立連線");
// 3 傳送資料
String msg = "歡迎使用";
DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
dos.writeUTF(msg);
dos.flush();
while(true){
}
}
}
}
package com.net.tcp.socket;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.net.UnknownHostException;
/**
* 1 建立客戶端 必須指定伺服器 + 埠 此時連線
* Socket(InetAddress host, int port)
* 接收資料 傳送資料
* @author lyy
*
*/
public class Client {
public static void main(String[] args) throws UnknownHostException, IOException {
// 1 、建立客戶端 必須指定伺服器 + 埠 此時連線
Socket client = new Socket("192.168.1.112", 8888);
// 2 接收資料
// BufferedReader br = new BufferedReader(new InputStreamReader(client.getInputStream()));
// String echo = br.readLine();//阻塞式的方法
// System.out.println(echo);
DataInputStream dis = new DataInputStream(client.getInputStream());
String echo = dis.readUTF();
System.out.println(echo);
}
}
7、小案例(強烈建議大家自己敲一遍,很好玩!)
使用的多執行緒、流以及socket通訊原理的方式,建立了一個公眾聊天室的demo,進入有系統提示,可以@名字說悄悄話等等,對socket整個知識點稍微瞭解了更加深入一點點,還是要多消化消化,今天做了一天了,頭有點大了,不說了上案例
package com.net.tcp.chat.demo4;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
/**
* 建立伺服器
* @author lyy
*
*/
public class Server {
private List<MyChanel> all = new ArrayList<MyChanel>();
public static void main(String[] args) throws IOException {
new Server().start();
}
public void start() throws IOException{
ServerSocket server = new ServerSocket(9999);
while(true){
Socket client = server.accept();
MyChanel channel = new MyChanel(client);
all.add(channel);//加入到容器中同意管理
new Thread(channel).start();//一條道路
}
}
/**
* 一個客戶端一個道路
* 1 輸入流
* 2 輸出流
* 3 接收資料
* 4 傳送資料
* @author lyy
*
*/
private class MyChanel implements Runnable{
private DataInputStream dis;
private DataOutputStream dos;
private boolean isRunning = true;
private String name;
public MyChanel(Socket client) {
try {
dis = new DataInputStream(client.getInputStream());
dos = new DataOutputStream(client.getOutputStream());
this.name = dis.readUTF();
this.send("歡迎你進入聊天室!");
sendOthers(this.name+"進入了聊天室",true);
} catch (IOException e) {
CloseUtil.closeAll(dis,dos);
isRunning = false;
}
}
/**
* 讀取資料
* @return
*/
private String receive(){
String msg = "";
try {
msg = dis.readUTF();
} catch (IOException e) {
CloseUtil.closeAll(dis);
isRunning = false;
all.remove(this);//移除自身
}
return msg;
}
/**
* 傳送資料
*/
public void send(String msg){
if(null == msg && !msg.equals("")){
return;
}
try {
dos.writeUTF(msg);
dos.flush();
} catch (IOException e) {
// e.printStackTrace();
CloseUtil.closeAll(dos);
isRunning = false;
all.remove(this);//移除自身
}
}
/**
* 傳送給其他客戶端
*/
private void sendOthers(String msg,boolean sys){
System.out.println(msg);
//是否為私聊 約定
if(msg.startsWith("@") && msg.indexOf(":") > -1){//表示私聊
String name = msg.substring(1, msg.indexOf(":"));
String conetnt = msg.substring(msg.indexOf(":")+1);
//獲取Name
for (MyChanel other : all) {
if(other.name.equals(name)){
other.send(this.name+"對您悄悄說"+conetnt);
}
}
}else{
//遍歷容器
for (MyChanel other : all) {
if(other == this){
continue;
}
if(sys){//系統資訊
//傳送給其他客戶端
other.send("系統資訊:"+msg);
}else{
//傳送給其他客戶端
other.send(this.name+":"+msg);
}
}
}
}
@Override
public void run() {
while(isRunning){
sendOthers(receive(),false);
}
}
}
}
package com.net.tcp.chat.demo4;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
/**
* 傳送資料執行緒
* @author lyy
*
*/
public class Send implements Runnable{
//控制檯的輸入流
private BufferedReader console;
//管道輸出流
private DataOutputStream dos;
//控制執行緒
private boolean isRunning = true;
//名稱
private String name;
public Send() {
console = new BufferedReader(new InputStreamReader(System.in));
}
public Send(Socket client , String name){
this();
try {
dos = new DataOutputStream(client.getOutputStream());
this.name = name;
send(this.name);
} catch (IOException e) {
// e.printStackTrace();
isRunning = false;
CloseUtil.closeAll(dos,console);
}
}
//從控制檯接收資料
private String getMsgFromConsole(){
try {
return console.readLine();
} catch (IOException e) {
e.printStackTrace();
}
return "";
}
/**
* 從控制檯接收資料
* 傳送資料
*/
public void send(String msg){
if(msg != null && !msg.equals("")){
try {
dos.writeUTF(msg);
dos.flush();//強制重新整理
} catch (IOException e) {
// e.printStackTrace();
isRunning = false;
CloseUtil.closeAll(dos,console);
}
}
}
@Override
public void run() {
//執行緒體
while(isRunning){
send(getMsgFromConsole());
}
}
}
package com.net.tcp.chat.demo4;
import java.io.DataInputStream;
import java.io.IOException;
import java.net.Socket;
/**
* 接收執行緒
* @author lyy
*
*/
public class Receive implements Runnable{
//輸入流
private DataInputStream dis;
//執行緒標識
private boolean isRunning = true;
public Receive() {
}
public Receive(Socket client){
try {
dis = new DataInputStream(client.getInputStream());
} catch (IOException e) {
// e.printStackTrace();
isRunning = false;
CloseUtil.closeAll(dis);
}
}
/**
* 接收資料
* @return
*/
public String receive(){
String msg ="";
try {
msg = dis.readUTF();
} catch (IOException e) {
isRunning = false;
CloseUtil.closeAll(dis);
}
return msg;
}
@Override
public void run() {
//執行緒體
while(isRunning){
System.out.println(receive());
}
}
}
<span style="font-size:18px;">package com.net.tcp.chat.demo4;
import java.io.Closeable;
import java.io.IOException;
/**
* 關閉流的方法
* @author lyy
*
*/
public class CloseUtil {
public static void closeAll(Closeable... io){
for(Closeable temp :io){
if(null != temp){
try {
temp.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
</span>
}
<span style="font-size:18px;">package com.net.tcp.chat.demo4;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.net.UnknownHostException;
/**
* 建立客戶端 傳送資料 + 接收資料
* 寫出資料 輸出流
* 讀取資料 輸入流
* @author lyy
*
* 輸入流和輸出流在同一個執行緒內 彼此獨立
*
*
*
*/
public class Client {
public static void main(String[] args) throws UnknownHostException, IOException {
System.out.println("請輸入名稱:");
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String name = br.readLine();
if(name.equals("")){
return;
}
Socket client = new Socket("localhost", 9999);
new Thread(new Send(client,name)).start();//一條路徑
new Thread(new Receive(client)).start();//一條路徑
}
}
</span>
學習了一天,感覺還是有很大的收穫的,需要多消化消化,希望大家也能從中收穫一點自己想要的東西,加油!
總結案例下載:http://download.csdn.net/detail/qq_14996421/9527603