TCP 通信原理
TCP 通信协议是一种牢靠的网络协议,它在通信的两端各建设一个 Socket 对象,从而在通信的两端造成虚构网络链路。一旦建设了虚构的网络链路,两端的程序就能够通过虚构链路进行通信
TCP 发送数据
发送数据步骤
- 创立客户端的 Socket 对象(Socket) Socket(String host,int port)
- 获取输入流,写数据
OutputStream getOutputStream() -
开释资源 void close()
// 创立客户端的 Socket 对象(Socket) //Socket(InetAddress address,int port)创立流套接字并将将其连贯到指定 IP 地址的指定端口号 Socket s = new Socket(InetAddress.getByName("192.168.1.66"),,port:10000);//alt enter 抛出异样 //Socket(String host,int port)创立流套接字并将将其连贯到指定 IP 地址的指定端口号 // 和后面那个一样 只是第一个参数能够间接是字符串地址 Socket s = new Socket(host:"192.168.1.66",port:10000);//alt enter 抛出异样 // 获取输入流,写数据 //OutputStream getOutputStream() 返回此套接字的输入流 OutputStream os = s.getOutputStream(); os.write(b:"hello,tcp, 我来了".getBytes()) // 开释资源 s.close();
TCP 接收数据
接收数据步骤
- 创立服务器端的 Socket 对象(ServerSocket)
ServerSocket(int port) - 监听客户端连贯,返回一个 Socket 对象 Socket accept()
- 获取输出流,读数据,并把数据显示在控制台 InputStream getInputStream()
-
开释资源 void close()
// 创立服务器端的 Socket 对象(ServerSocket) //ServerSocket(int port)创立绑定到指定端口的服务器套接字 ServerSocket ss = new ServerSocket(port:10000);//alt enter 抛出异样 //Socket accept() 侦听要连贯到此套接字并承受它 Socket s = ss.accept(); // 获取输出流,读数据,并把数据显示在控制台 //InputStream getInputStream() 返回此套接字的输入流 InputStream is = s.getInputStream(); byte[] bys = new byte[1024]; int len = is.read(bys);// 拿到的是理论发送了多少数据 String dataString = new String(bys,offset:0,len); sout("数据是:"+dataString); // 开释资源 s.close(); ss.close();
TCP 通信程序练习
练习 1
- 客户端:发送数据,接管服务器反馈
-
服务器:接收数据,给出反馈
客户端程序// 创立客户端的 Socket 对象(Socket) Socket s = new Socket(host:"192.168.1.66",port:10000);//alt enter 抛出异样 // 获取输入流,写数据 OutputStream os = s.getOutputStream(); os.write(b:"hello,tcp, 我来了".getBytes()) // 接管服务器反馈 InputStream is = s.getInputStream(); byte[] bys = new byte[1024]; int len = is.read(bys);// 拿到的是理论发送了多少数据 String data = new String(bys,offset:0,len); sout("客户端:"+data); // 开释资源 s.close();
服务器端程序
// 创立服务器端的 Socket 对象(ServerSocket) ServerSocket ss = new ServerSocket(port:10000);//alt enter 抛出异样 // 监听客户端连贯,返回一个 Socket 对象 Socket s = ss.accept(); // 获取输出流,读数据,并把数据显示在控制台 InputStream is = s.getInputStream(); byte[] bys = new byte[1024]; int len = is.read(bys);// 拿到的是理论发送了多少数据 String data = new String(bys,offset:0,len); sout("服务器:"+data); // 给出反馈 OutputStream os = s.getOutputStream(); os.write("数据曾经收到".getBytes()); // 开释资源 s.close(); ss.close();
练习 2
- 客户端:数据来自于键盘录入,直到输出的数据是 886,发送数据完结
-
服务器:接管到的数据在控制台输入
客户端程序// 创立客户端的 Socket 对象(Socket) Socket s = new Socket(host:"192.168.1.66",port:10000);//alt enter 抛出异样 // 数据来自于键盘录入,直到输出的数据是 886,发送数据完结 BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); // 封装输入流对象 BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));// 字节输入流转化成字符流,而后用 BufferedWriter 写数据封装 String line; while((line=br.readLine())!=null){//alt enter 抛出异样 // 所输出的数据是 886,发送数据完结 if("886".equals(line)){break;} // 如果不是,就获取输入流对象 //OutputStream os = s.getOutputStream(); //os.write(b:"hello,tcp, 我来了".getBytes()); bw.write(line); bw.newLine(); bw.flush();} // 开释资源 s.close();
服务器端程序
// 创立服务器端的 Socket 对象(ServerSocket) ServerSocket ss = new ServerSocket(port:10000);//alt enter 抛出异样 // 监听客户端连贯,返回一个对应的 Socket 对象 Socket s = ss.accept(); // 获取输出流,读数据,并把数据显示在控制台 InputStream is = s.getInputStream(); InputStreamReader isr = new InputStreamReader(is); BufferedReader br = new BufferedReader(isr); // 下面三步合并为 BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));// 输出流转化成字符流,再包装成 BufferedReader String line; while((line=br.readLine())!=null){//alt enter 抛出异样 sout(line); } // 开释资源 ss.close();
练习 3
- 客户端:数据来自于键盘录入,直到输出的数据是 886,发送数据完结
-
服务器:接管到的数据写入文本文件
客户端程序// 创立客户端的 Socket 对象(Socket) Socket s = new Socket(host:"192.168.1.66",port:10000);//alt enter 抛出异样 // 数据来自于键盘录入,直到输出的数据是 886,发送数据完结 BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); // 封装输入流对象 BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));// 字节输入流转化成字符流,而后用 BufferedWriter 写数据封装 String line; while((line=br.readLine())!=null){//alt enter 抛出异样 // 所输出的数据是 886,发送数据完结 if("886".equals(line)){break;} // 如果不是,就获取输入流对象 //OutputStream os = s.getOutputStream(); //os.write(b:"hello,tcp, 我来了".getBytes()); bw.write(line); bw.newLine(); bw.flush();} // 开释资源 s.close();
服务器端程序
// 创立服务器端的 Socket 对象(ServerSocket) ServerSocket ss = new ServerSocket(port:10000);//alt enter 抛出异样 // 监听客户端连贯,返回一个对应的 Socket 对象 Socket s = ss.accept(); // 接收数据 BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));// 输出流转化成字符流,再包装成 BufferedReader // 把数据写入文本文件 BufferedWriter bw = new BufferedWriter(new FileWriter(fileName:"myNet\\s.txt")); String line; while((line=br.readLine())!=null){//alt enter 抛出异样 bw.write(line); bw.newLine(); bw.flush();} // 开释资源 bw.close(); ss.close();
练习 4
- 客户端:数据来自于文本文件
-
服务器:接管到的数据写入文本文件
客户端程序// 创立客户端的 Socket 对象(Socket) Socket s = new Socket(host:"192.168.1.66",port:10000);//alt enter 抛出异样 // 数据来自于文本文件 // 封装文本文件的数据 BufferedReader br = new BufferedReader(new FileReader(fileName:"myNet\\InetAddressDemo.java")); // 封装输入流写数据 BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));// 字节输入流转化成字符流,而后用 BufferedWriter 写数据封装 // 读数据,并且把它写出去 String line; while((line=br.readLine())!=null){//alt enter 抛出异样 bw.write(line); bw.newLine(); bw.flush();} // 开释资源 br.close(); s.close();
服务器端程序
// 创立服务器端的 Socket 对象(ServerSocket) ServerSocket ss = new ServerSocket(port:10000);//alt enter 抛出异样 // 监听客户端连贯,返回一个对应的 Socket 对象 Socket s = ss.accept(); // 接收数据 BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));// 输出流转化成字符流,再包装成 BufferedReader // 把数据写入文本文件 BufferedWriter bw = new BufferedWriter(new FileWriter(fileName:"myNet\\Copy.java")); String line; while((line=br.readLine())!=null){//alt enter 抛出异样 bw.write(line); bw.newLine(); bw.flush();} // 开释资源 bw.close(); ss.close();
练习 5
- 客户端:数据来自于文本文件,接管服务器反馈
-
服务器:接管到的数据写入文本文件,给出反馈
- 呈现问题:程序始终期待
- 起因:读数据的办法是阻塞式的
客户端程序
// 创立客户端的 Socket 对象(Socket) Socket s = new Socket(host:"192.168.1.66",port:10000);//alt enter 抛出异样 // 数据来自于文本文件 // 封装文本文件的数据 BufferedReader br = new BufferedReader(new FileReader(fileName:"myNet\\InetAddressDemo.java")); // 封装输入流写数据 BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));// 字节输入流转化成字符流,而后用 BufferedWriter 写数据封装 // 读数据,并且把它写出去 String line; while((line=br.readLine())!=null){//alt enter 抛出异样 bw.write(line); bw.newLine(); bw.flush();} // 自定义完结标记 //bw.write(str:"886"); //bw.newLine(); //bw.flush(); //public void shutdownOutput() s.shutdownOutput(); // 接管服务器的反馈 BufferedReader brClient = new BufferedReader(new InputStreamReader(s.getInputStream())); String data = brClient.readLine();// 期待读取数据 sout("服务器的反馈:"+data); // 开释资源 br.close(); s.close();
服务器端程序
// 创立服务器端的 Socket 对象(ServerSocket) ServerSocket ss = new ServerSocket(port:10000);//alt enter 抛出异样 // 监听客户端连贯,返回一个对应的 Socket 对象 Socket s = ss.accept(); // 接收数据 BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));// 输出流转化成字符流,再包装成 BufferedReader // 把数据写入文本文件 BufferedWriter bw = new BufferedWriter(new FileWriter(fileName:"myNet\\Copy.java")); String line; while((line=br.readLine())!=null){//alt enter 抛出异样 还在这等着读数据呢 // if("886".equals(line)){ // break; // } bw.write(line); bw.newLine(); bw.flush();} // 给出反馈 BufferedWriter bwServer = new BufferedWriter(new OutputStreamWriter(s.getOutputStream())); bwServer.write(str:"文件上传胜利"); bwServer.newLine(); bwServer.flush(); // 开释资源 bw.close(); ss.close();
练习 6
- 客户端:数据来自于文本文件,接管服务器反馈
-
服务器:接管到的数据写入文本文件,给出反馈,代码用线程进行封装,为每一个客户端开启一个线程
客户端程序// 创立客户端的 Socket 对象(Socket) Socket s = new Socket(host:"192.168.1.66",port:10000);//alt enter 抛出异样 // 数据来自于文本文件 // 封装文本文件的数据 BufferedReader br = new BufferedReader(new FileReader(fileName:"myNet\\InetAddressDemo.java")); // 封装输入流写数据 BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));// 字节输入流转化成字符流,而后用 BufferedWriter 写数据封装 // 读数据,并且把它写出去 String line; while((line=br.readLine())!=null){//alt enter 抛出异样 bw.write(line); bw.newLine(); bw.flush();} // 自定义完结标记 //bw.write(str:"886"); //bw.newLine(); //bw.flush(); //public void shutdownOutput() s.shutdownOutput(); // 接管服务器的反馈 BufferedReader brClient = new BufferedReader(new InputStreamReader(s.getInputStream())); String data = brClient.readLine();// 期待读取数据 sout("服务器的反馈:"+data); // 开释资源 br.close(); s.close();
服务器端程序
// 创立服务器端的 Socket 对象(ServerSocket) ServerSocket ss = new ServerSocket(port:10000);//alt enter 抛出异样 while(true){ // 监听客户端连贯,返回一个对应的 Socket 对象 Socket s = ss.accept(); // 为每一个客户端开启一个线程 new Thread(new ServerThread(s)).start();}
创立一个类实现线程
public class ServerThread implements Runnable{ private Socket s; public ServerThread (Socket s){this.s = s;} // 重写 run 办法 @Override public void run(){ // 接收数据,写到文本文件 BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));//try catch 捕捉异样 //BufferedWriter bw = new BufferedWriter(new FileWriter(fileName:"myNet\\Copy.java"));// 解决名称抵触问题 int count = 0; File file = new File(pathname:"myNet\\Copy["+count+"].java"); while(file.exists()){ count++; file = new File(pathname:"myNet\\Copy["+count+"].java"); } BufferedWriter bw = new BufferedWriter(new FileWriter(file));String line; while((line=br.readLine())!=null){bw.write(line); bw.newLine(); bw.flush();} // 给出反馈 BufferedWriter bwServer = new BufferedWriter(new OutputStreamWriter(s.getOutputStream())); bwServer.write(str:"文件上传胜利"); bwServer.newLine(); bwServer.flush(); // 开释资源 s.close();} }