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()));//输出流转化成字符流,再包装成BufferedReaderString 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(); }}