初學socket程式設計(網路程式設計)
阿新 • • 發佈:2018-12-01
socket程式設計可以理解為是一種二進位制+IP+埠的一種通訊模式,在任何語言中,都有socket程式設計,因此幾乎所有語言的socket都可以互通。只要是涉及到通訊方面的如QQ,微信等都是涉及到socket,只是他們自己進行了封裝。socket的本質是對tcp/ip的封裝。
網路通訊:
UDP:是面向無連線的,所以效率較高,不會建立連線,不安全。不管有沒有接收方,只管向指定地址傳送東西。(但要求大小在64k以內)底層使用UDP協議。
TCP:是面向連線的,三次握手成功之後才能通訊,位元組流傳輸,效率低於UDP,但是安全性高(因為採用了三次握手和四次揮手協議)。雙方需要建立連線才能通訊(傳送資料)。底層使用TCP協議,TCP底層是用HTTP協議。
TCP三次握手四次揮手示意圖:
TCP通訊實現:
先建立伺服器端:
//TCP協議服務端 public class Server { public static void main(String[] args) throws IOException { System.out.println("TCP服務端啟動了"); //啟動服務端 ServerSocket serverSocket = new ServerSocket(8080);//傳入埠號 //等待客戶端連線(如果客戶端不連線進來,程式一直阻塞在這裡等待) Socket accept = serverSocket.accept(); //模擬客戶端給服務端傳送訊息的場景 //生成輸入流 InputStream is = accept.getInputStream(); //定義位元組 byte [] bytes = new byte[1024]; //讀取 int length = is.read(bytes); //將byte陣列轉為String String result = new String(bytes, 0, length); System.out.println("伺服器端已經接收到客戶端傳送的訊息:"+result); } }
TCP客戶端:
//TCP客戶端 public class TCPClient { public static void main(String[] args) throws Exception, IOException { //建立socket Socket socket = new Socket("127.0.0.1", 8080);//傳入IP和埠號 //建立輸出流 OutputStream os = socket.getOutputStream(); //先定義一段話 String mes = "hello"; //傳送 os.write(mes.getBytes()); System.out.println("客戶端傳送訊息完畢"); } }
先執行伺服器端:
執行客戶端:
訊息傳送完成後,我們再看服務端列印的內容:
下面我們繼續寫一下伺服器接收到訊息後的反饋,伺服器端:
//TCP協議服務端
public class Server {
public static void main(String[] args) throws IOException {
//啟動服務端
ServerSocket serverSocket = new ServerSocket(8080);
try {
System.out.println("TCP服務端啟動了");
//等待客戶端連線(如果客戶端不連線進來,程式一直阻塞在這裡等待)
Socket accept = serverSocket.accept();
//模擬客戶端給服務端傳送訊息的場景
//生成輸入流
InputStream is = accept.getInputStream();
//定義位元組
byte [] bytes = new byte[1024];
//讀取
int length = is.read(bytes);
//將byte陣列轉為String
String result = new String(bytes, 0, length);
System.out.println("伺服器端已經接收到客戶端傳送的訊息:"+result);
//返回訊息
//得到一個OutputStream
OutputStream outputStream = accept.getOutputStream();
//將輸出流轉為列印流
PrintWriter pw = new PrintWriter(outputStream);
pw.print("我是伺服器,已經收到訊息");
pw.flush();
accept.shutdownOutput();
} catch (Exception e) {
// TODO: handle exception
}finally {
//使用try,萬一程式碼出現異常,我們就在finally中關閉連線
serverSocket.close();
}
}
}
客戶端:
//TCP客戶端
public class TCPClient {
public static void main(String[] args) throws Exception, IOException {
//建立socket
Socket socket = new Socket("127.0.0.1", 8080);//傳入IP和埠號
try {
//建立輸出流
OutputStream os = socket.getOutputStream();
//先定義一段話
String mes = "hello";
//傳送
os.write(mes.getBytes());
System.out.println("客戶端傳送訊息完畢");
//獲取服務端傳送的訊息
//獲取InputStream
InputStream is = socket.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
//讀
String result = br.readLine();
System.out.println("客戶端===》》伺服器返回的結果:"+result);
} catch (Exception e) {
}finally {
socket.close();
}
}
}
先執行服務端:
再執行客戶端:
此時再看服務端:
UDP實現:
先建立UDP服務端:
//UDP服務端
public class UdpServer {
public static void main(String[] args) throws IOException {
System.out.println("udp服務啟動了");
//定義DatagramSocket
DatagramSocket ds = new DatagramSocket(8080);//不傳地址,預設本級
//建立接收的陣列
byte [] buf = new byte[1024];
//獲取客戶端傳送的資料
DatagramPacket dp = new DatagramPacket(buf, buf.length);
//直到有客戶端連線起來,程式才會執行下去,否則一直阻塞在這裡
ds.receive(dp);
String string = dp.getAddress().toString();
String data = new String(dp.getData(),0,dp.getLength());
System.out.println("伺服器接收從IP:"+string+"傳輸的資料"+data);
}
}
建立UDP客戶端:
//udp客戶端
public class UdpClient {
public static void main(String[] args) throws IOException {
DatagramSocket ds = new DatagramSocket();//此處不用傳引數
//定義傳送的資料
String mes = "hello";
byte[] bytes = mes.getBytes();
DatagramPacket dp = new DatagramPacket(bytes, bytes.length,new InetSocketAddress("127.0.0.1",8080));
//傳送資料
ds.send(dp);
ds.close();
System.out.println("客戶端傳送資訊完畢");
}
}
先啟動服務端:
再啟動客戶端:
再看服務端:
下面我們來驗證一下UDP是無連線的,傳送訊息時不會關心服務端是否在。我們關掉服務端,啟動客戶端,此時不會出現異常錯誤,即驗證上述。然後我們關掉服務端和客戶端,再重新啟動服務端和客戶端時,剛才在服務端沒有啟動時傳送的資料已經被覆蓋掉了,所以服務端接收到的是它啟動之後的資料。