【Java TCP/IP Socket程式設計】----套接字----TCP Socket
簡介
TCP通訊嚴格區分客戶端和伺服器端,通訊時客戶端發起請求連線伺服器端才能實現通訊,伺服器端不能主動連線客戶端。Java為TCP協議提供了兩個類:Socket類和ServerSocket類,一個Socket例項代表了TCP連線的客戶端,而ServerSocket例項代表了TCP連線的伺服器端。一個TCP連線是一條抽象的雙向通道,兩端分別由IP地址和埠號確定。開始通訊之前,要建立一個TCP連線,這需要先由客戶端TCP向服務端TCP傳送連線請求。ServerSocket例項則監聽TCP連線請求,併為每個請求建立新的Socket例項,也就是說伺服器端要同時處理ServerSocket例項和Socket例項,而客戶端只需要使用Socket例項。
TCP通訊
TCP客戶端:
客戶端向伺服器發起連線請求,就被動地等待伺服器的響應。典型的TCP客戶端要經過下面三步。
1.建立一個Socket例項:建構函式向指定的遠端主機和埠建立一個TCP連線。
2.通過套接字的輸入輸出流進行通訊,一個Socket連線例項包括了一個InputStream和一個OutputStream。
3.使用Socket類的close()方法關閉連線。
TCP伺服器端:
伺服器端的工作是建立一個通訊終端,並被動地等待客戶端的連線。典型的TCP伺服器質性如下工作:
1.建立一個ServerSocket例項並指定本地埠。此套接字的功能是監聽改指定埠收到的連線。
2.重複執行:
a.呼叫ServerSocket的accept()方法以獲取下一個客戶端連線。基於新建立的客戶端連線,建立一個Socket例項,並由accept()方法返回。
b.使用所返回的Socket例項的InputStream和OutputStream與客戶端進行通訊。
c.通訊完成後,使用Socket類的close()方法關閉該客戶端套接字連線。
TCP通訊案例
以下程式碼實現了客戶端傳送檔案到伺服器端,伺服器端進行接收並儲存檔案,接收完檔案給客戶端反饋。
此案例使用多執行緒實現的,由此服務端可以接收到多個客戶端傳送過來的檔案。
public class TCPClient {
public static void main(String[] args) {
try {
Socket clientSocket = new Socket("127.0.0.1", 1234);
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("D:\\java.txt"));
OutputStream out = clientSocket.getOutputStream();
int len = 0;
byte[] buffer = new byte[1027];
while ((len = bis.read(buffer)) != -1) {
out.write(buffer, 0, len);
}
// 資料傳送完畢,關閉socket輸出操作,告知伺服器端
clientSocket.shutdownOutput();
// ---------讀取伺服器端的反饋資訊
InputStream in = clientSocket.getInputStream();
byte[] message = new byte[1024];
int length = in.read(message);
System.out.println(new String(message, 0, length));
// 關閉套接字和流
clientSocket.close();
bis.close();
out.close();
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public class ServerTask implements Runnable {
private Socket clientSocket;
public ServerTask(Socket socket) {
this.clientSocket = socket;
}
@Override
public void run() {
try {
InetAddress address = clientSocket.getInetAddress();
System.out.println("message from ip:" + address.getHostAddress());
InputStream in = clientSocket.getInputStream();
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("D:\\upload"+System.currentTimeMillis()+".txt"));
int len = 0;
byte[] buffer = new byte[1024];
while ((len = in.read(buffer)) != -1) {
bos.write(buffer, 0, len);
}
// --------給客戶端反饋
OutputStream out = clientSocket.getOutputStream();
out.write("finish the job".getBytes());
in.close();
bos.close();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public class TCPServer {
public static void main(String[] args) throws IOException {
//監聽埠1234
ServerSocket serverSocket = new ServerSocket(1234);
while(true) {
//請求啟用一個執行緒處理
Socket clientSocket = serverSocket.accept();
new Thread(new ServerTask(clientSocket)).start();
}
//serverSocket.close();
}
}