上面我们了解了Udp编程,接下来让我们再来看看Tcp编程
首先分析一下Udp和Tcp之间的区别?
1)Udp是无连接,接收端只管接收;而Tcp是基于面向里连接的(例如打电话的时候你得先拨号码)
2)Udp无法确保数据的安全传送,有可能会丢失数据;而Tcp是可以保证安全传输的
3)Udp是通过创建数据报包进行传输的,而Tcp是通过流的模式去进行传输的
4)Udp效率高传输速度快,但是安全性低;Tcp效率低传输速度慢,安全性高
Tcp编程的原理分析:
1)同样需要客户端和服务端都创建Socket对象,并且两者的端口号必须一致
2)服务端必须去监听客户端的连接,这样二者之间就会产生一种通道连接
3)当通道产生后,可以通过字节流去写数据给服务器端或者服务器端也可以反馈信息给客户端
4)最后关闭资源
首先用Tcp进行简单的数据传输
package com.westos.Tcp; import java.io.IOException; import java.io.OutputStream; import java.net.Socket; /** *Tcp编程的引入 * */ public class ClientDome { public static void main(String[] args) throws IOException { /** * 1)创建Socket类对象 * 构造方法: * public Socket(String host, int port):创建客户端套接字对象,并且指定端口号和ip文本形式 */ Socket s=new Socket("192.168.43.204",12334); /** * 2)获取通道内的输出流对象 * public OutputStream getOutputStream():获取套接字 的输出流 */ OutputStream out = s.getOutputStream(); /** * 3)给服务器端写数据 */ out.write("成吉思汗,只识弯弓射大雕".getBytes()); /** * 4)当服务器反馈给我们信息后客户端也应该去接收它 */ InputStream in = s.getInputStream(); //获取数据 byte[] bys=new byte[1024]; int len = in.read(bys); System.out.println(new String(bys,0,len)); //5)关闭资源 s.close(); } }
package com.westos.Tcp; import java.io.IOException; import java.io.InputStream; import java.net.ServerSocket; import java.net.Socket; public class ServerDome { public static void main(String[] args) throws IOException { /** * 1)创建ServerSocket类对象 * public ServerSocket(int port) throws IOException创建绑定到特定端口的服务器套接字 */ ServerSocket ss=new ServerSocket(12334); /** * 2)监听客户端的连接 */ Socket s = ss.accept(); /** * 3)获取通道内的输入流对象 */ InputStream in = s.getInputStream(); /** * 4)读取数据 */ byte[] bys=new byte[1024]; int len = in.read(bys); String data=new String(bys,0,len); String ip = s.getInetAddress().getHostAddress(); /** * 5)输出数据 */ System.out.println("from"+ip+"data is:"+data); /** * 6)当我们的服务器端收到客户端的数据后,就需要反馈给客户端 * 获取通道内的输出流对象 */ OutputStream out = s.getOutputStream(); out.write("数据已经收到...".getBytes()); /** * 7)关闭资源 */ s.close(); } }
练习1:
当我们想要去实现字符的传输时,应该怎么做?
package com.westos.Tcp02; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.net.Socket; /** *客户端 :去实现字符的传输 */ public class ClientDome { public static void main(String[] args) throws IOException { //创建Socket对象 Socket s=new Socket("192.168.43.204",1112); //创建字符缓冲输入流的录入方式 BufferedReader br=new BufferedReader(new InputStreamReader(System.in)); //封装数据通道中的输出流 BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(s.getOutputStream())); //写入数据 String line=null; while((line=br.readLine())!=null) { //进行结束的条件 if("over".equals(line)) { break; } //写入读取的数据 bw.write(line); bw.newLine(); bw.flush(); } //关闭资源(在这里不要关闭bw和br,因为它要不停的录入数据和读取数据,) s.close(); } }
package com.westos.Tcp02; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.ServerSocket; import java.net.Socket; /** * 服务器端 * */ public class ServerDome { public static void main(String[] args) throws IOException { //创建Socket类对象 ServerSocket ss=new ServerSocket(1112); //去监听客户端的连接 Socket s = ss.accept(); //封装通道内的输入流对象 BufferedReader br=new BufferedReader(new InputStreamReader(s.getInputStream())); //读取数据 String line=null; while((line=br.readLine())!=null) { System.out.println(line); } //关闭资源 s.close(); } }
练习2:
当我们想将客户端中的文本里的数据传输给服务器端应该怎么做?
package com.westos.Tcp03; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.FileReader; import java.io.IOException; import java.io.OutputStreamWriter; import java.net.Socket; /** *将客户端中的文本中的数据传输给服务器端,并展示在控制台上 * */ public class ClientText { public static void main(String[] args) throws IOException { //创建Socket类对象 Socket s=new Socket("192.168.43.204",2202); //创建字符输入流对象 BufferedReader br=new BufferedReader(new FileReader("ReceiveDome.java")); //封装通道中的输出流对象 BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(s.getOutputStream())); //读取文本中的数据并且写进通道中 String line=null; while((line=br.readLine())!=null) { bw.write(line); bw.newLine(); bw.flush(); } //关闭资源 s.close(); br.close(); } }
package com.westos.Tcp03; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.ServerSocket; import java.net.Socket; public class ServerDome { public static void main(String[] args) throws IOException { //创建Socket类对象 ServerSocket ss=new ServerSocket(2202); //去监听客户端的连接 Socket s = ss.accept(); //创建字符缓冲输入流对象 BufferedReader br=new BufferedReader(new InputStreamReader(s.getInputStream())); String line=null; while((line=br.readLine())!=null) { System.out.println(line); } //关闭资源 s.close(); } }
练习3:
当我们想将客户端中的文本数据copy到服务器端的文件中应该怎么做?
package com.westos.Tcp04; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.FileReader; import java.io.IOException; import java.io.OutputStreamWriter; import java.net.Socket; /** * 需求:将客户端中的文本数据复制到服务器端的一个文本中 * */ public class ClientDome { public static void main(String[] args) throws IOException { //创建Socket对象 Socket s=new Socket("192.168.43.204",23456); //创建字符缓冲输入流对象 BufferedReader br=new BufferedReader(new FileReader("ReceiveDome.java")); //封装通道中的输入流对象 BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(s.getOutputStream())); //一遍读取一遍写数据 String line=null; while((line=br.readLine())!=null) { bw.write(line); bw.newLine(); bw.flush(); } //当你发送数据完毕后,需要通知服务器端去接收数据 s.shutdownOutput(); //当服务器端反馈给你信息后需要你去接收它 //创建通道中的输入流对象 BufferedReader bwClient=new BufferedReader (new InputStreamReader(s.getInputStream())); String str = bwClient.readLine(); System.out.println(str); //关闭资源 s.close(); br.close(); } }
package com.westos.Tcp04; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.FileWriter; import java.io.IOException; import java.io.InputStreamReader; import java.net.ServerSocket; import java.net.Socket; public class ServerDome { public static void main(String[] args) throws IOException { //创建Socket类对象 ServerSocket ss=new ServerSocket(23456); //监听客户端的连接 Socket s = ss.accept(); //创建字符缓冲输出流对象 BufferedWriter bw=new BufferedWriter(new FileWriter("copy.java")); //封装通道中的输入流对象 BufferedReader br=new BufferedReader(new InputStreamReader(s.getInputStream())); //读取并写入数据 String line=null; while((line=br.readLine())!=null) { bw.write(line); bw.newLine(); bw.flush(); } //数据读取完毕后需要给客户端反馈读取完毕的信息 //创建通道中的字符缓冲输出流对象 BufferedWriter bwServer=new BufferedWriter(new OutputStreamWriter(s.getOutputStream())); bwServer.write("文本复制好了..."); bwServer.newLine(); bwServer.flush(); //关闭资源 s.close(); bw.close(); } }
练习4:
将图片进行复制,但是在复制的时候有一些要点需要我们注意:
1)复制图片的时候,我们应该运用字节流而不是字符流
2)在图片复制完成后,我们会发现图片的内存有差,没有完全加载完,这是需要我们的OutputStream类中的Flush方法去强制刷新数据
例如:
package com.westos.Tcp05; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.net.Socket; /* * 这里我们将进行图片的复制 * 这里将不能使用字符流的形式了,应该改成字节流 */ public class ClientDome { public static void main(String[] args) throws IOException { //创建Socket类对象 Socket s=new Socket("192.168.43.204",2345); //封装通道中的输出流对象 BufferedOutputStream bos=new BufferedOutputStream(s.getOutputStream()); //创建字节缓冲输入流对象 BufferedInputStream bis=new BufferedInputStream(new FileInputStream("图7.jpg")); //读取数据 byte[] bys=new byte[1024]; int len=0; while((len=bis.read(bys))!=-1) { bos.write(bys, 0, len); //flush() :刷新此输出流并强制写出所有缓冲的输出字节 bos.flush(); } //通知服务器端去接收数据 s.shutdownOutput(); //接收服务器端的反馈信息 InputStream in = s.getInputStream(); byte[] b=new byte[1024]; int l = in.read(b); String date=new String(b, 0, l); System.out.println(date); //关闭资源 s.close(); bis.close(); } }
package com.westos.Tcp05; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket; public class ServerDome { @SuppressWarnings("resource") public static void main(String[] args) throws IOException { //创建Socket对象 ServerSocket ss=new ServerSocket(2345); //监听客户端的连接 Socket s = ss.accept(); //封装通道内的输入流对象 BufferedInputStream bis=new BufferedInputStream(s.getInputStream()); //创建字节缓冲输出流对象 BufferedOutputStream bos=new BufferedOutputStream(new FileOutputStream("copy.jpg")); //读写数据 byte[] bys=new byte[1024]; int len=0; while((len=bis.read(bys))!=-1) { bos.write(bys, 0, len); //flush() :刷新此输出流并强制写出所有缓冲的输出字节 bos.flush(); } //读取完毕后反馈给客户端 OutputStream out = s.getOutputStream(); out.write("图片已经复制好了...".getBytes()); //关闭资源 s.close(); bos.close(); } }