這是我最頭疼的問題之一。。。問題本身不難,但是要提前考慮清楚一些細節。另外,我第一次面試就遇到一個問題:如果想把一個項目的數據導入到另一個項目中,我們該用什麼技術。我當時一臉懵逼,啥?數據該從數據庫拿就從數據庫拿,該從文件拿就從文件拿。。。結果面試老師說是網絡編程。。。我還能說什麼呢???說實話我從來沒想過用網絡編程來幹這個,我學的都是來來來,我給你發一條消息,你接收一下,完了給我個回覆之類的。
socket
又叫套接字,網絡編程中最基礎,最重要的概念,socket包含IP和端口號。socket通信:網絡上的兩個程序通過一個雙向通訊連接實現數據的交換,這個雙向鏈路的一端稱爲Socket
一) 網絡地址分類
1. A類地址分配給規模特別大的網絡使用。
分配給具有大量主機(直接個人用戶)
而局域網絡個數較少的大型網絡。例如IBM公司的網絡。
2. B 類地址 設計B類地址的目的是支持中到大型的網絡。
3. C 類地址 C類地址用於支持大量的小型網絡。
注:
在編程前,需要測試你和對方的網絡是否通暢
通過ipconfig獲取自己的ip
通過ping ip測試你們是否能通信
二) TCP/IP五層網絡架構:
1.物理層:主要定義物理設備標準,
如網線的接口類型、光纖的接口類型、
各種傳輸介質的傳輸速率等。
它的主要作用是傳輸比特流(就是由1、0轉化爲電流強弱來進行傳輸,
到達目的地後在轉化爲1、0,也就是我們常說的數模轉換與模數轉換)。
這一層的數據叫做比特。
2. 數據鏈路層:
主要將從物理層接收的數據進行MAC地址(網卡的地址)的封裝與解封裝。
常把這一層的數據叫做幀。
在這一層工作的設備是交換機,數據通過交換機來傳輸。
3. 網絡層:
主要將從下層接收到的數據進行IP地址(例192.168.0.1)的封裝與解封裝。
在這一層工作的設備是路由器,常把這一層的數據叫做數據包。
4. 傳輸層:定義了一些傳輸數據的協議和端口號(WWW端口80等),
如:TCP(傳輸控制協議,傳輸效率低,可靠性強,用於傳輸可靠性要求高,數據量大的數據),
UDP(用戶數據報協議,與TCP特性恰恰相反,用於傳輸可靠性要求不高,數據量小的數據。
7.應用層:直接爲用戶的應用進程提供服務,比如說FTP(各種文件下載),WEB(瀏覽器), QQ, 微信
注:關於tcp/ip的網絡架構這裏可能不全,有需要可以網上找相關資料
三 )通信三要素
兩臺計算機通信
ip: 確定主機地址
協議: 通信的規則
端口: 1~65535, 每一個端口標識一個進程
四) 重點
1) 基於tcp的通信
a)客戶端發送信息,服務器接收
b)客戶端發送信息,服務器回覆,客戶端在接收
c)使用多線程,創建多客戶端連接的服務器
2) 基於udp的通信
a) 發送端發送消息,接收端接受
b) A端線發送,後接受, B端先接受後發送
關於網絡編程,上面是最基本的5個案例,下面分別用代碼來實現
package socketProgramming;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
public class Tcp1_ServerDemo {
/**
* tcp有三個例子,這是第一個
* @throws IOException
*
*/
public static void main(String[] args) throws IOException {
//1.創建服務端,監聽固定端口
ServerSocket server=new ServerSocket(12345);
//2.阻塞,等待客戶端連接
while(true){
Socket socket=server.accept();
String ip=socket.getInetAddress().getHostName();
System.out.println("客戶端連接成功");
//3.獲取流對象
InputStream is=socket.getInputStream();
BufferedReader br=new BufferedReader(new InputStreamReader(is));
//4.讀取數據
String msg=br.readLine();
System.out.println(ip+":"+msg);
is.close();
br.close();
socket.close();
}
}
}
package socketProgramming;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
public class Tcp1_ClientDemo {
public static void main(String[] args) throws UnknownHostException, IOException {
//1.創建客戶端
Socket socket=new Socket("localhost",12345);
System.out.println("連接服務器");
//2.獲取流對象
OutputStream os=socket.getOutputStream();
byte[]byts="你好,我是客戶端".getBytes();
os.write(byts);
os.close();
socket.close();
}
}
==============第二個例子=============
package socketProgramming;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class Tcp2_ServerDemo {
/**
* tcp有三個例子,這是第二個
* @throws IOException
*
*/
public static void main(String[] args) throws IOException {
//1.創建服務端,監聽固定端口
ServerSocket server=new ServerSocket(10086);
//2.等待客戶端連接
Socket socket=server.accept();
String ip=socket.getInetAddress().getHostName();
System.out.println(ip+"客戶端連接成功");
//3.獲取流對象
InputStream is=socket.getInputStream();
BufferedReader br=new BufferedReader(new InputStreamReader(is));
OutputStream os=socket.getOutputStream();
//4.讀取數據
String msg=br.readLine();
System.out.println(ip+":"+msg);
//注意關閉輸入流,否則沒效果
socket.shutdownInput();
String msg_output="已經接收到數據";
os.write(msg_output.getBytes());
is.close();
br.close();
socket.close();
}
}
package socketProgramming;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
public class Tcp2_ClientDemo {
public static void main(String[] args) throws UnknownHostException, IOException {
//1.創建客戶端
Socket socket=new Socket("localhost",10086);
System.out.println("連接服務器");
//2.獲取流對象
OutputStream os=socket.getOutputStream();
byte[]byts="你好,我是客戶端".getBytes();
InputStream is=socket.getInputStream();
BufferedReader br=new BufferedReader(new InputStreamReader(is));
//3.
os.write(byts);
//注意關閉輸出流,否則沒效果
socket.shutdownOutput();
String msg=br.readLine();
System.out.println("服務器回覆的數據:"+msg);
is.close();
br.close();
os.close();
socket.close();
}
}
// 這個例子需要強調的就是不同方向的流的衝突問題,用完一個方向的流及時關閉
==============第三個例子====================
package socketProgramming;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
public class Tcp3_ServerDemo {
/**
* tcp有三個例子,這是第三個,多客戶端連接
* @throws IOException
*
*/
static ArrayList<Socket> alist=new ArrayList<>();
public static void main(String[] args) throws IOException {
//1.創建服務端,監聽固定端口
ServerSocket server=new ServerSocket(10086);
System.out.println("服務器啓動。。。");
//2.等待客戶端連接
while(true){
Socket socket=server.accept();
alist.add(socket);
System.out.println("在線人數"+alist.size());
//創建線程,與客戶端通信
new Tcp3_SocketThread(socket).start();
}
}
}
package socketProgramming;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
public class Tcp3_ClientDemo {
public static void main(String[] args) throws UnknownHostException, IOException {
//1.創建客戶端
Socket socket=new Socket("localhost",10086);
System.out.println("連接服務器");
//2.獲取流對象
OutputStream os=socket.getOutputStream();
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
//3.發送數據
String line=null;
System.out.println("請輸入內容,輸出886退出");
while((line=br.readLine())!=null){
if("886".equals(line)){
break;
}
//下面這句必須加,不加沒效果
line=line+"\r\n";
os.write(line.getBytes());
os.flush();
}
br.close();
os.close();
socket.close();
}
}
package socketProgramming;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
public class Tcp3_SocketThread extends Thread{
private Socket socket;
public Tcp3_SocketThread(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
String ip=socket.getInetAddress().getHostName();
System.out.println(ip+"連接進來");
//獲取流對象
BufferedReader br=null;
try {
br=new BufferedReader(new InputStreamReader(socket.getInputStream()));
//讀取客戶端發來的數據
String line=null;
while((line=br.readLine())!=null){
System.out.println(ip+":"+line);
}
br.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
=================第四個例子==================
package socketProgramming;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
public class Udp1_Receive {
/**
* 基於UDP有兩個例子,這是第一個例子,也是我的第4個例子
* @throws IOException
*
*/
public static void main(String[] args) throws IOException {
//1.創建socket
DatagramSocket receive=new DatagramSocket(12302);
//2.接收數據
byte[] buf=new byte[1024];
DatagramPacket packet=new DatagramPacket(buf, 0, buf.length);
receive.receive(packet);//阻塞,等待接收
String ip=packet.getAddress().getHostAddress();
System.out.println(ip+":"+new String(packet.getData()));
//3.關閉資源
receive.close();
}
}
package socketProgramming;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
public class Udp1_Send {
/**
* 這是udp第一個例子的另一端
* @throws IOException
*/
public static void main(String[] args) throws IOException {
DatagramSocket socket=new DatagramSocket();
String str="你好,客戶端";
byte []data=str.getBytes();
InetAddress address=InetAddress.getByName("127.0.0.1");
DatagramPacket packet=new DatagramPacket(data,data.length,address,12302);
socket.send(packet);
socket.close();
}
}
===============這是最後一個例子==============
package socketProgramming;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
public class Udp2_Receive {
/**
* 這是udp第二個例子,A端線發送,後接受, B端先接受後發送
* 需要注意的是,udp之間通信沒有固定的服務端和客戶端,通信雙方平等
* 一端發送,另一端 就接收,反之亦然
*/
public static void main(String[] args) {
//1.創建socket對象
DatagramSocket socket=null;
try {
socket=new DatagramSocket(11111);
//2.獲取數據
byte []buf=new byte[1024];
DatagramPacket packet=new DatagramPacket(buf, buf.length);
socket.receive(packet);//接收數據
String ip=packet.getAddress().getHostAddress();
System.out.println(ip+":"+new String(packet.getData()));
//3.發送數據
byte[]reply ="你好,我收到消息".getBytes();
DatagramPacket replyPacket=new DatagramPacket(reply, reply.length,InetAddress.getByName("127.0.0.1"),10086);
socket.send(replyPacket);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
if(socket!=null){
socket.close();
}
}
}
}
package socketProgramming;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
public class Udp2_Send {
public static void main(String[] args) {
//1.創建對象
DatagramSocket socket=null;
try {
socket=new DatagramSocket(10086);
//2.發送數據
byte[]msg="你好,我是發送端,我線發送數據".getBytes();
DatagramPacket packet=new DatagramPacket(msg, msg.length,InetAddress.getByName("127.0.0.1"),11111);
socket.send(packet);
//3.獲取數據
byte []buf=new byte[1024];
DatagramPacket receivePacket =new DatagramPacket(buf, buf.length);
socket.receive(receivePacket);
String ip=receivePacket.getAddress().getHostAddress();
System.out.println(ip+":"+new String(receivePacket.getData()));
} catch (SocketException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
if(socket!=null){
socket.close();
}
}
}
}
至此,網絡編程的五個簡單例子已經寫完,需要注意的一點是,運行程序時先運行接收端,再運行發送端,否則可能接收不到數據,上面五個例子是筆者挨個測試的可以運行,還有就是一些細節,比如幾個固定的類以及他們的方法,目前我的理解就這樣,以後有機會繼續添加