不久前接到黑馬程序員的一道題目關於TCP協議的題目,苦思良久,卻只能馬虎的做出來而已,即使寫出代碼了,那也是參考他人的,還沒有正確理解其中的道理。今天突然回來看這道題,覺得挺有意思,於是又重新整理了一番,
/**
* 題目:使用TCP協議完成一個客戶端一個服務器。客戶端從鍵盤輸入讀取一個字符串,發送到服務器。
服務器接收客戶端發送的字符串,反轉之後發回客戶端。客戶端接收並打印。
思路:
1.創建客戶端類,完成鍵盤錄入和發送請求
1.1創建套接字,關聯好服務器地址和端口號
1.2通過套接字獲取字節輸出流,另一方面建立鍵盤錄入
1.3將鍵盤錄入通過字節輸出流將字符發送給服務端
1.4將相關資源關閉
2.創建客戶端類,完成客戶端的接收請求並將接收到的字符反轉後發回客戶端。
2.1創建服務端套接字
2.2關聯客戶端套接字
2.3通過套接字獲取字節輸入流(獲取客戶端發送請求(字符串))和字節輸出流(將字符串反轉後發送給客戶端)
2.4關閉相關資源
*
*/
1.創建客戶端類,完成鍵盤錄入和發送請求
</pre><pre class="html" name="code">class Client{
public static void main(String[] args) {
// TODO Auto-generated method stub
//創建客戶端,初始爲null
Socket s=null;
BufferedReader input=null;
try {
s=new Socket("192.168.1.105",10005);
input=new BufferedReader(new InputStreamReader(System.in));
PrintWriter out=new PrintWriter(s.getOutputStream(),true);
InputStream in=s.getInputStream();
String data=null;
int len=0;
while((data=input.readLine())!=null){
out.println(data);
byte[]buf=new byte[1024];
len=in.read(buf);
String responseData=new String(buf,0,len);
System.out.println(responseData);
}
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
throw new RuntimeException("找不到主機");
} catch (IOException e) {
// TODO Auto-generated catch block
throw new RuntimeException("獲取流失敗");
}finally{
try {
if(s!=null){
s.close();
}
} catch (IOException e) {
throw new RuntimeException("套接字關閉失敗");
}finally{
try {
if(input!=null)
input.close();
} catch (Exception e2) {
throw new RuntimeException("鍵盤輸入流關閉失敗");
}
}
}
}
}
2.創建服務端類,獲取客戶端請求和回送字符串
</pre><pre class="java" name="code">class Server{
public static void main(String[] args) throws IOException {
new Server().server();
}
public void server() throws IOException{
ServerSocket ss=new ServerSocket(10005);
Socket s=ss.accept();
//獲取客戶端ip
String ip=s.getInetAddress().getHostAddress();
//通過客戶端套接字獲取輸入流,讀取客戶端發送的數據
InputStream in=s.getInputStream();
PrintWriter out=new PrintWriter(s.getOutputStream(),true);
byte[]buf=new byte[1024];
int len=0;
while((len=in.read(buf))!=-1){
//定義變量,將從客戶端接收到的數據轉化爲字符串
String acceptData=new String(buf,0,len);
for(int i=acceptData.length()-1;i>=0;i--){
//將從客戶端那接收到的字符串發送回客戶端
out.print((acceptData.charAt(i)));
}
out.println();
}
s.close();
ss.close();
}
}
建立好客戶端類和服務端類後,在dos那先運行服務端類,然後在運行客戶端類,這時候你在客戶端類上發送請求,就可以看到反轉回來的字符串了
如圖:
在網絡編程中,TCP協議安全係數比較高,怎麼說呢?就像我們打電話,電話撥通了,必須要有人接,才能進行通話。也就是說,當客戶端發出請求後,必須得到服務端迴應後,才能進行下一步操作,否則將進入到阻塞狀態。
本人也通過編寫了一道程序,從這道程序中可以更能清楚的看到TCP的通信過程,客戶端輸入請求後,必須等到服務端迴應了之後,才能繼續發出請求,服務端在接到請求後,也要回應給客戶端後,才能接受到下一個請求。相關代碼如下:
客戶端代碼:
package com.net;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
public class TcpClient {
public static void main(String[] args) throws Exception {
new TcpClient().send();
}
public void send() throws Exception{
Socket s=new Socket("192.168.1.105",10003);
PrintWriter out=new PrintWriter(s.getOutputStream(),true);
BufferedReader input=new BufferedReader(new InputStreamReader(System.in));
InputStream in=s.getInputStream();
String ip=s.getInetAddress().getHostAddress();
String data=null;
byte []buf=new byte[1024];
int len=0;
while((data=input.readLine())!=null){
if("over".equals(data))
break;
out.println(data);
len=in.read(buf);
String responseData=new String(buf,0,len);
System.out.println(ip+"::"+responseData);
}
input.close();
s.close();
}
}
服務端代碼:
package com.net;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
public class TcpServer {
public static void main(String[] args) throws IOException {
new TcpServer().accept();
}
public void accept() throws IOException{
ServerSocket ss=new ServerSocket(10003);
Socket s=ss.accept();
String ip=s.getInetAddress().getHostAddress();
InputStream is=s.getInputStream();
PrintWriter out=new PrintWriter(s.getOutputStream(),true);
BufferedReader in=new BufferedReader(new InputStreamReader(System.in));
byte[]buf=new byte[1024];
int len=0;
while((len=is.read(buf))!=-1){
String data=new String(buf,0,len);
System.out.println(ip+"::accept data="+data);
String responseData=in.readLine();
out.println(responseData);
}
s.close();
ss.close();
}
}