Socket
套接字使用TCP提供了兩臺計算機(jī)之間的通信機(jī)制。 客戶端程序創(chuàng)建一個套接字,并嘗試連接服務(wù)器的套接字。
當(dāng)連接建立時,服務(wù)器會創(chuàng)建一個 Socket 對象??蛻舳撕头?wù)器現(xiàn)在可以通過對 Socket 對象的寫入和讀取來進(jìn)行通信。
java.net.Socket 類代表一個套接字,并且 java.net.ServerSocket 類為服務(wù)器程序提供了一種來監(jiān)聽客戶端,并與他們建立連接的機(jī)制。
以下步驟在兩臺計算機(jī)之間使用套接字建立TCP連接時會出現(xiàn):
服務(wù)器實例化一個 ServerSocket 對象,表示通過服務(wù)器上的端口通信。
服務(wù)器調(diào)用 ServerSocket 類的 accept() 方法,該方法將一直等待,直到客戶端連接到服務(wù)器上給定的端口。
服務(wù)器正在等待時,一個客戶端實例化一個 Socket 對象,指定服務(wù)器名稱和端口號來請求連接。
Socket 類的構(gòu)造函數(shù)試圖將客戶端連接到指定的服務(wù)器和端口號。如果通信被建立,則在客戶端創(chuàng)建一個 Socket 對象能夠與服務(wù)器進(jìn)行通信。
在服務(wù)器端,accept() 方法返回服務(wù)器上一個新的 socket 引用,該 socket 連接到客戶端的 socket。
連接建立后,通過使用 I/O 流在進(jìn)行通信,每一個socket都有一個輸出流和一個輸入流,客戶端的輸出流連接到服務(wù)器端的輸入流,而客戶端的輸入流連接到服務(wù)器端的輸出流。
TCP 是一個雙向的通信協(xié)議,因此數(shù)據(jù)可以通過兩個數(shù)據(jù)流在同一時間發(fā)送.
Socket 類的構(gòu)造方法和普通方法
用Socket類實現(xiàn)客戶端向服務(wù)器端發(fā)送消息
/**
* 網(wǎng)絡(luò)編程:
* 在兩臺不同的計算機(jī)之間傳遞數(shù)據(jù)
*
* 客戶端:Apps 瀏覽器 pc軟件
* 服務(wù)器端:存儲/處理數(shù)據(jù)
*
* URL:統(tǒng)一的資源定位
* http:www.baidu.com/search?code=android&type=1
* http/https: 傳輸協(xié)議 Tcp/IP
* www.baidu.com : 域名 表示一臺網(wǎng)絡(luò)中的電腦
* ipv4 ipv6地址:唯一標(biāo)識一臺網(wǎng)絡(luò)中的計算機(jī)
* 32位: 4個部分每個8字節(jié)
*
* DNS服務(wù)器:域名解析
* 將www.baidu.com類型的域名解析為對應(yīng)的ip地址
* search 對應(yīng)的后臺程序文件 php java jsp
* ? 表示運(yùn)行這個程序需要傳遞的參數(shù)
* code=android code是服務(wù)器端規(guī)定的字段
* & 如果有多個參數(shù)使用&符號鏈接
*
* ip地址:唯一標(biāo)識某一臺電腦
* 端口號:唯一標(biāo)識電腦上的某一個進(jìn)程(程序)80
*
* 數(shù)據(jù)傳輸:TCP/IP協(xié)議
* TCP:面向鏈接的 安全的
* UDP:面向無鏈接的 不安全 但快
*
* 網(wǎng)絡(luò)中的數(shù)據(jù)傳輸:Socket
* Socket:客戶端
* ServerSocket:服務(wù)器端
* */
//模擬客戶端
class Client {
public static void main(String[] args) throws IOException {
//1.創(chuàng)建用于通信的socket
// 指明和誰通信:ip地址 端口號
Socket socket = new Socket("ip",8989);
// 接收服務(wù)器端的數(shù)據(jù)
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//讀取服務(wù)器端發(fā)來的數(shù)據(jù)
String line = null;
while ((line = br.readLine()) != null){
System.out.println(line);
}
// 客戶端向服務(wù)器端發(fā)送數(shù)據(jù)
PrintStream ps = new PrintStream(socket.getOutputStream());
ps.println("你好啊");
socket.shutdownOutput();
}
}
//模擬服務(wù)器端
class Server{
public static void main(String[] args) throws IOException {
//1.創(chuàng)建服務(wù)器端的serverocket
ServerSocket ss = new ServerSocket(8989);
//2.獲取連接的客戶端的socket
Socket clientSocket = ss.accept();
//3.向客戶端發(fā)送數(shù)據(jù)
//BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream()));
PrintStream ps = new PrintStream(clientSocket.getOutputStream());
ps.println("登錄成功");
clientSocket.shutdownOutput();
//4.接收客戶端發(fā)來的數(shù)據(jù)
BufferedReader br = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
String line = null;
while ((line = br.readLine()) != null){
System.out.println(line);
}
}
}
升級版:消息由終端手動輸入:
/**
* 手動輸入內(nèi)容 發(fā)送
* Socket扮演的是客戶端
* ServerSocket扮演的是服務(wù)器端
*
*/
class MyClient {
public static void main(String[] args){
//連接服務(wù)器端的socket
Socket socket = null;
try{
socket = new Socket("ip",8888);
//接收服務(wù)器端信息
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line;
while ((line = br.readLine()) != null){
System.out.println(line);
}
//從鍵盤輸入數(shù)據(jù) 發(fā)送給服務(wù)器端
} catch (IOException e) {
System.out.println("網(wǎng)絡(luò)出錯 請重新登錄");
} finally {
//關(guān)閉連接
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
class MyServer {
public static void main(String[] args){
//創(chuàng)建ServerSocket
try (ServerSocket ss = new ServerSocket(8888)){
//監(jiān)聽客戶端的連接
Socket socket = ss.accept();
//從終端接收數(shù)據(jù)
BufferedReader keyin = new BufferedReader(new InputStreamReader(System.in));
//獲取向客戶端輸出數(shù)據(jù)的輸出流
PrintStream ps = new PrintStream(socket.getOutputStream());
String line = null;
while ((line = keyin.readLine()) != null){
//發(fā)送給客戶端
ps.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
實現(xiàn)客戶端向服務(wù)器端發(fā)送圖片:
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;
public class Meida {
}
class MeidaClient{
public static void main(String[] args) throws IOException {
//連接服務(wù)器 獲取socket
Socket socket = new Socket("ip",8080);
//創(chuàng)建服務(wù)器端對應(yīng)的輸入流 用于接收服務(wù)器端發(fā)來的數(shù)據(jù)
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
System.out.println(br.readLine());
//向服務(wù)器端發(fā)送文件(圖片)
//1.將文件寫入到內(nèi)存里
String path = "D:\\桌面\\pokerplaymind.png";
FileInputStream fis = new FileInputStream(path);
//2.創(chuàng)建字節(jié)流 outputStream
BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
byte[] buf = new byte[1024];
int len;
while ((len = fis.read(buf)) != -1){
bos.write(buf,0,len);
}
socket.shutdownOutput();
}
}
class MediaServer{
public static void main(String[] args) throws IOException {
//創(chuàng)建服務(wù)器端的ServerSoket
ServerSocket ss = new ServerSocket(8080);
//監(jiān)聽客戶端連接
//當(dāng)有客戶端來連接這個服務(wù)器 就可以得到對應(yīng)的socket
//當(dāng)沒有客戶端來連接 服務(wù)器一直在這里等待
Socket socket = ss.accept();
//創(chuàng)建客戶端對應(yīng)的輸出流 用于向這個客戶端發(fā)送數(shù)據(jù)
PrintStream ps = new PrintStream(socket.getOutputStream());
ps.println("連接成功 可以發(fā)數(shù)據(jù)了!");
BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
String path = "D:\\Android learning\\java2\\821Day13\\src\\main\\java\\swu\\w1nfred\\a821day13\\1.png";
FileOutputStream fos = new FileOutputStream(path);
byte[] buf = new byte[1024];
int len;
while((len = bis.read(buf)) != -1){
fos.write(buf,0,len);
}
}
}
多線程實現(xiàn)單服務(wù)器多客戶端傳遞數(shù)據(jù):
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
public class Myclass {
}
/**
*
*
* */
class Server{
//保存每一個連接過來的Socket對象
public static ArrayList<Socket> sockets = new ArrayList<>();
public static void main(String[] args)throws IOException {
ServerSocket ss =new ServerSocket(8888);
//不停的等待客戶端來連接
while(true) {
Socket socket = ss.accept();
//當(dāng)有客戶端連接過來 就保存
sockets.add(socket);
//開啟一個線程 處理每個客戶端的輸入
new ServerThread(socket).start();
}
}
}
class ServerThread extends Thread{
private Socket socket;
public ServerThread(Socket socket){
this.socket = socket;
}
@Override
public void run() {
BufferedReader br = null;
try {
br= new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line = null;
while((line = br.readLine())!=null){
//群發(fā)消息
//遍歷Server維護(hù)的數(shù)組
for (Socket s:Server.sockets) {
//向socket對應(yīng)的客戶端發(fā)送消息
PrintStream ps = new PrintStream(s.getOutputStream());
ps.println(line);
}
}
} catch (IOException e) {
System.out.println("網(wǎng)絡(luò)錯誤 請重新登錄");
System.exit(-1);
}finally {
//關(guān)閉輸入輸出流
//關(guān)閉對應(yīng)的socket連接
try {
if(br != null){
br.close();}
if(socket !=null){
socket.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
super.run();
}
}
class Client{
public static void main(String[] args)throws IOException {
Socket socket = new Socket("ip",8888);
//主線程處理終端輸入 發(fā)送給服務(wù)器端
//用一個子線程處理服務(wù)器端數(shù)據(jù)
new Thread(new ClientThread(socket)).start();
BufferedReader keyin = new BufferedReader(new InputStreamReader(System.in));
PrintStream ps = new PrintStream(socket.getOutputStream());
String line = null;
while((line = keyin.readLine())!=null){
ps.println(line);
}
}
}
/**
* 創(chuàng)建一個子線程處理客戶端接收服務(wù)器端數(shù)據(jù)
*
* */
class ClientThread implements Runnable{
private Socket socket;
public ClientThread(Socket socket){
this.socket = socket;
}
@Override
public void run() {
BufferedReader br = null;
try {
//獲取服務(wù)器端的輸入流對象
br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//讀取數(shù)據(jù)
String line;
while((line = br.readLine())!=null){
System.out.println(line);
}
} catch (IOException e) {
System.out.println("網(wǎng)絡(luò)出錯 請重新登錄");
System.exit(-1);
}finally {
if(br != null){
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(socket !=null){
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
chaos
最后編輯于 :
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。