摘要:JAVA 網路
兩方通訊概念
- 先有對方ip
- 數據傳送到對方指定的應用程序上,以網路應用程序進行標誌,以數字代表,稱為埠
- 通信規則,即協議(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
- 建立客戶端與服務器端
- 建立連接後,通過Socket中的IO流進行數據傳書
- 關閉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();
}
}
客戶端給服務端發送數據,服務端收到後,給客戶端反饋訊息
- 建立Socket服務,指定要連接的主機與埠
- 獲取Socket流中的輸出流,將數據寫到該流中,通過網路發送給服務端
- 獲取Socket流中的輸入流,將服務端反饋的數據獲取到,並印出
- 關閉客戶端資源
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();
}
}