網路
兩方通訊概念
1. 先有對方ip
2. 數據傳送到對方指定的應用程序上,以網路應用程序進行標誌,以數字代表,稱為埠
3. 通信規則,即協議(TCP/IP)
IP地址
網路中設備的標誌,可用主機名,本地為127.0.0.1(localhotst)
埠:
標誌進程的邏輯地址,不用進程標誌,有效端口0~65536
UDP:
將數據及源和目的的封裝成數據包中,不需要建立連接,每個數據限制在64KB內,因無連接,所以為不可靠協議,不需要建立連接,速度快
TCP:
建立連接,形成傳輸數據的通道,在連接中進行大數據傳輸,通過三次握手完成連接,是可靠協議,必須建立連接,效率會稍低
查看本機:
import java.net.*;
class Hello{
public static void main(String[]
args)throws Exception{
InetAddress i = InetAddress.getLocalHost();
System.out.print(i);
}
}
|
查看Google本機:
import java.net.InetAddress; class Hello{ public static void main(String[] args)throws Exception{ InetAddress ia = InetAddress.getByName("www.google.com.tw"); System.out.print(ia);
} } |
Socket:
網路服務提供的一種機制,通信的兩端都有socket,數據在兩個socket間通過IO傳輸
DatagarmSocket
void
receive(DatagramPacket p)
void
send(DatagaramPacket p)
class UdpReceive{ public static void main(String[] args)throws Exception{
//創建udp socket建立端點 DatagramSocket ds = new DatagramSocket(10000); while(true){//無窮迴圈等待接收 //定義數據包用於存儲數據 byte[] buf = new byte[1024]; DatagramPacket dp = new DatagramPacket(buf, buf.length);
//通過服務的receive方法將收到的數據存入數據包中 ds.receive(dp);
String ip = dp.getAddress().getHostAddress(); String output = new String (dp.getData(), 0 , dp.getLength()); int port = dp.getPort();
System.out.println(ip + "::" + output + "::" + port); } //關閉資源 //ds.close(); } } |
//需求: 通過udp傳輸方式,將一段文字數據發送出去
/**
* 1. 建立udpsocket服務
* 2. 提供數據, 並將數據封裝至數據包中
* 3. 通過socket服務的發送功能, 將數據包發出去*/
class Hello{ public static void main(String[] args)throws Exception{
//創建udp服務 通過DatagramSocket物件 DatagramSocket ds = new DatagramSocket();
//確定數據,並封裝成數據包 byte[] data = "udp 123123".getBytes(); DatagramPacket dp =
new DatagramPacket(data, data.length, InetAddress.getByName("192.168.1.254"), 10000);
//通過socket服務 將已有的數據包發送出去 通過send方法 ds.send(dp); //關閉資源 ds.close(); } } |
class Hello{
public static void main(String[]
args)throws Exception{
DatagramSocket ds = new DatagramSocket();
BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
String
line = null;
while((line
= bufr.readLine()) != null){
if("88".equals(line))
break;
byte[]
buf = line.getBytes();
DatagramPacket dp =
new DatagramPacket(buf,
buf.length, InetAddress.getByName("114.34.185.121"), 10001);
ds.send(dp);
}
ds.close();
}
}
class UdpReceive{
public static void main(String[] args)throws
Exception{
DatagramSocket ds = new DatagramSocket(10001);
while(true){
byte[]
buf = new byte[1024];
DatagramPacket dp = new DatagramPacket(buf,
buf.length);
ds.receive(dp);
String ip
= dp.getAddress().getHostAddress();
String
data = new String
(dp.getData(), 0 ,
dp.getLength());
System.out.println(ip + "::" +
data);
}
}
}
|
//192.168.1.255廣播
聊天範例
使用多執行緒來操作發送數據與接收數據
一個執行緒發送、一個執行緒接收
class Hello{
public static void main(String[]
args)throws Exception{
DatagramSocket sendSoket = new DatagramSocket();
DatagramSocket receivedSoket = new DatagramSocket(10002);
new Thread(new Send(sendSoket)).start();
new Thread(new Receive(receivedSoket)).start();
}
}
class Send implements
Runnable{
private
DatagramSocket ds;
Send(DatagramSocket
ds){
this.ds
= ds;
}
public void run(){
try{
BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
String
line = null;
while((line
= bufr.readLine()) != null){
if("88".equals(line))
break;
byte[]
buf = line.getBytes();
DatagramPacket dp =
new DatagramPacket(buf,
buf.length, InetAddress.getByName("192.168.1.255"), 10002);
ds.send(dp);
}
ds.close();
}catch(Exception
e){
throw new RuntimeException("發送失敗");
}
}
}
class Receive implements
Runnable{
private
DatagramSocket ds;
Receive(DatagramSocket
ds){
this.ds
= ds;
}
public void run(){
try{
BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
String
line = null;
while(true){
byte[]
buf = new byte[1024];
DatagramPacket dp = new DatagramPacket(buf,
buf.length);
ds.receive(dp);
String ip
= dp.getAddress().getHostAddress();
String
data = new String
(dp.getData(), 0 ,
dp.getLength());
System.out.println(ip + "::" +
data);
}
}catch(Exception
e){
throw new RuntimeException("接收失敗");
}
}
}
|
TCP:
Socker與ServerSocket
1. 建立客戶端與服務器端
2. 建立連接後,通過Socket中的IO流進行數據傳書
3. 關閉Socket
import java.io.OutputStream; import java.net.Socket; //客戶端: //通過查閱socket物件,發現在該物件建立時,就可以去連接指定主機 //因為tcp是物件導向,所以在建立socket時,就要有服務端存在,並連接成功 //連接後,在該通道進行數據的傳輸
class TcpClient{ public static void main(String[] args)throws Exception{ Socket s = new Socket("114.34.185.121", 10006); //為了發送數據,應該獲取socket流中的輸出流 OutputStream out = s.getOutputStream();
out.write("客戶端發送".getBytes()); s.close();
} }
import java.io.IOException; import java.io.InputStream; import java.net.ServerSocket; import java.net.Socket;
//服務端: //建立服務端的socket服務 ServeSocket();並監聽一個埠 //獲取連接過來的客戶端物件,通過ServerSocket的accept方法(阻塞式) //客戶端如果發送數據,服務端要使用對應的客戶端物件,並獲取到該客戶端物件的讀取流來讀取//數據,關閉服務器(可選)
class TcpServer{ public static void main(String[] args) throws IOException{ ServerSocket ss = new ServerSocket(10006); Socket s = ss.accept();
String ip = s.getInetAddress().getHostAddress(); System.out.println(ip + "... connected ");
InputStream in = s.getInputStream();
byte[] buf = new byte[1024]; int len = in.read(buf); System.out.println(new String(buf, 0, len)); s.close();
ss.close();
} } |
客戶端給服務端發送數據,服務端收到後,給客戶端反饋訊息
1. 建立Socket服務,指定要連接的主機與埠
2. 獲取Socket流中的輸出流,將數據寫到該流中,通過網路發送給服務端
3. 獲取Socket流中的輸入流,將服務端反饋的數據獲取到,並印出
4. 關閉客戶端資源
import java.io.InputStream; import java.io.OutputStream; import java.net.Socket;
class TcpClient { public static void main(String[] args)throws Exception{ Socket s = new Socket("114.34.185.121", 10006);
OutputStream out = s.getOutputStream();
out.write("客戶端發送".getBytes());
InputStream in = s.getInputStream();
byte[] buf = new byte[1024]; int len = in.read(buf); System.out.println(new String(buf, 0, len)); s.close();
} }
import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket;
class TcpServer{ public static void main(String[] args) throws IOException{ ServerSocket ss = new ServerSocket(10006); Socket s = ss.accept();
String ip = s.getInetAddress().getHostAddress(); System.out.println(ip + "... connected ");
InputStream in = s.getInputStream();
byte[] buf = new byte[1024]; int len = in.read(buf); System.out.println(new String(buf, 0, len));
OutputStream out = s.getOutputStream();
out.write("收到訊息".getBytes()); s.close();
ss.close();
} } |
需求: 建立一個文本轉換服務器
客戶端傳送資料給服務端,服務端會將文本轉為大寫後再傳送給客戶端
客戶端可以持續傳送,直接傳送over結束
import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.net.Socket;
//客戶端 //使用io操作方式 來源:由鍵盤輸入 目的:網路設備輸出流 //操作文本數據,可以選擇字元流
class TcpServer { public static void main(String[] args)throws Exception{ Sockets = new Socket("114.34.185.121", 10006); //讀取鍵盤輸入 BufferedReader bufr =
new BufferedReader(new InputStreamReader(System.in)); //將數據寫入到socket輸出流,發給服務端 BufferedWriter bufOut =
new BufferedWriter(new OutputStreamWriter(s.getOutputStream())); BufferedReader bufIn =
new BufferedReader(new InputStreamReader(s.getInputStream()));
String line = null; while((line = bufr.readLine()) != null){ if("over".equals(line)) break; bufOut.write(line);
bufOut.newLine();//發送enter給服務端 bufOut.flush();//刷新 String str = bufIn.readLine(); System.out.println("Server:" + str);
} bufr.close();
s.close();
} }
import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.net.ServerSocket; import java.net.Socket; //服務端 //來源: socket讀取流,目的:socket輸出流
class TcpServer{ public static void main(String[] args) throws IOException{ ServerSocket ss = new ServerSocket(10006); Socket s = ss.accept();
String ip = s.getInetAddress().getHostAddress(); System.out.println(ip + "... connected "); //讀取socket數據 BufferedReader bufIn =
new BufferedReader(new InputStreamReader(s.getInputStream())); //目的 socket輸出流 將大寫數據寫入到socket輸出流 //並發送給輸出端 BufferedWriter bufOut =
new BufferedWriter(new OutputStreamWriter(s.getOutputStream())); String line = null; while((line = bufIn.readLine()) != null){ bufOut.write(line.toUpperCase());
bufOut.newLine();
bufOut.flush();
} s.close();
ss.close();
} } |
服務端接收數據並儲存到檔案中
import java.io.BufferedReader; import java.io.FileReader; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.Socket;
class Hello{ public static void main(String[] args)throws Exception{ Socket s = new Socket("114.34.185.121", 10006);
BufferedReader bufr =
new BufferedReader(new FileReader("C:\\Test.txt"));
PrintWriter out = new PrintWriter(s.getOutputStream(), true);
String line = null; while((line = bufr.readLine()) != null){ out.println(line);
} s.shutdownOutput();//關閉客戶端輸出流,相當於給流中加入一個結束標記 -1
BufferedReader bufIn =
new BufferedReader(new InputStreamReader(s.getInputStream())); String str = bufIn.readLine(); System.out.println(str);
bufr.close();
s.close();
} }
import java.io.BufferedReader; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.ServerSocket; import java.net.Socket;
class TcpServer{ public static void main(String[] args) throws IOException{ ServerSocket ss = new ServerSocket(10006); Socket s = ss.accept();
String ip = s.getInetAddress().getHostAddress(); System.out.println(ip + "... connected ");
BufferedReader bufIn = new BufferedReader(new InputStreamReader(s.getInputStream())); PrintWriter out = new PrintWriter(new FileOutputStream("C:\\Server.txt"), true);
String line = null; while((line = bufIn.readLine()) != null){ if("over".equals(line)) break; out.println(line);
} PrintWriter pw = new PrintWriter(s.getOutputStream(), true); pw.println("上傳成功");
out.close();
s.close();
ss.close();
} } |
上傳圖片
import java.io.FileInputStream; import java.io.InputStream; import java.io.OutputStream; import java.net.Socket;
class Hello{ public static void main(String[] args)throws Exception{ Socket s = new Socket("114.34.185.121", 10006); FileInputStream fis = new FileInputStream("1.bmp"); OutputStream out = s.getOutputStream();
byte[] buf = new byte[1024]; int len = 0; while((len = fis.read(buf)) != -1){ out.write(buf, 0, len); } s.shutdownOutput();
InputStream in = s.getInputStream();
byte[] bufIn = new byte[1024]; int num = in.read(bufIn); System.out.println(new String(bufIn, 0, num));
fis.close();
s.close();
} }
import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket;
class TcpServer{ public static void main(String[] args) throws IOException{ ServerSocket ss = new ServerSocket(10006); Socket s = ss.accept();
String ip = s.getInetAddress().getHostAddress(); System.out.println(ip + "... connected ");
InputStream in = s.getInputStream();
FileOutputStream fos = new FileOutputStream("server.bmp");
byte[] buf = new byte[1024]; int len = 0; while((len = in.read(buf)) != -1){ fos.write(buf, 0, len); } OutputStream out = s.getOutputStream();
out.write("上傳成功".getBytes());
fos.close();
s.close();
ss.close();
} } |
服務端
當a連接上後,被服務端獲取到,服務端執行具體流程
若b也要連接,會成為等待狀態,因為服務端還沒有處理完a的請求
為了解決此問題,則服務端最好就是將每個客戶端封裝到一個單獨的執行緒中,這樣才能同時處理多的客戶端請求
import java.io.FileInputStream; import java.io.InputStream; import java.io.OutputStream; import java.net.Socket;
class Hello{ public static void main(String[] args)throws Exception{ Socket s = new Socket("114.34.185.121", 10006); FileInputStream fis = new FileInputStream("1.bmp"); OutputStream out = s.getOutputStream();
byte[] buf = new byte[1024]; int len = 0; while((len = fis.read(buf)) != -1){ out.write(buf, 0, len); } s.shutdownOutput();
InputStream in = s.getInputStream();
byte[] bufIn = new byte[1024]; int num = in.read(bufIn); System.out.println(new String(bufIn, 0, num));
fis.close();
s.close();
} }
import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket;
class TcpServer{ public static void main(String[] args) throws IOException{ ServerSocket ss = new ServerSocket(10006); while(true){ Socket s = ss.accept();
new Thread(new PicThread(s)).start(); } } }
class PicThread implements Runnable{ private Socket s; public PicThread(Socket s) { this.s = s; } public void run(){ int count = 1; String ip = s.getInetAddress().getHostAddress(); try{ System.out.println(ip + "... connected "); InputStream in = s.getInputStream();
File file = new File(ip +"("+(count)+")" + ".jpg"); while(file.exists()) file = new File(ip +"("+(count++)+")" + ".jpg");
FileOutputStream fos = new FileOutputStream(file);
byte[] buf = new byte[1024]; int len = 0; while((len = in.read(buf)) != -1){ fos.write(buf, 0, len); } OutputStream out = s.getOutputStream();
out.write("上傳成功".getBytes());
fos.close();
s.close();
}catch(Exception e){ throw new RuntimeException(ip + "上傳失敗"); } } } |
登錄範例
import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.Socket;
class Hello{ public static void main(String[] args)throws Exception{ Socket s = new Socket("114.34.185.121", 10006); BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in)); PrintWriter out = new PrintWriter(s.getOutputStream(), true); BufferedReader bufIn = new BufferedReader(new InputStreamReader(s.getInputStream()));
for(int x = 0; x < 3; x++){ String line = bufr.readLine(); if(line == null) break; out.println(line);
String info = bufIn.readLine(); System.out.println("info:" + info); if(info.contains("Welcome")) break; } bufr.close();
s.close();
} }
import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.ServerSocket; import java.net.Socket;
class TcpServer{ public static void main(String[] args) throws IOException{ ServerSocket ss = new ServerSocket(10006); while(true){ Socket s = ss.accept();
new Thread(new UserThread(s)).start(); } } }
class UserThread implements Runnable{ private Socket s; public UserThread(Socket s) { this.s = s; } public void run(){ String ip = s.getInetAddress().getHostAddress(); System.out.println(ip + "...connected"); try{ for(int x = 0; x < 3; x++){ BufferedReader bufIn = new BufferedReader(new InputStreamReader(s.getInputStream())); String name = bufIn.readLine(); BufferedReader bufr = new BufferedReader(new FileReader("G:\\user.txt")); PrintWriter out = new PrintWriter(s.getOutputStream(), true); String line = null;
boolean flag = false; while((line = bufr.readLine())!= null){ if(line.equals(name)){ flag = true; break; } } if(flag){ System.out.println(name + "登入"); out.println(name + " Welcome!"); break; }else{ System.out.println(name + "嘗試登入"); out.println(name + "用戶不存在");
} } s.close();
}catch(Exception e){ throw new RuntimeException(ip + "校驗失敗"); } } } |
客戶端與服務端
客戶端:瀏覽器
服務端:自定義
import java.io.IOException; import java.io.PrintWriter; import java.net.ServerSocket; import java.net.Socket;
class TcpServer{ public static void main(String[] args) throws IOException{ ServerSocket ss = new ServerSocket(10006); // http://192.168.0.1:10006/ Socket s = ss.accept();
System.out.println(s.getInetAddress().getHostAddress());
PrintWriter out = new PrintWriter(s.getOutputStream(), true); out.println("客戶端你好"); s.close();
ss.close();
} } |
沒有留言:
張貼留言