不久前接到黑马程序员的一道题目关于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();
}
}