设立网络编程最根本性的原因是实现计算机之间的通信.
一台计算机想要与另一台计算机进行通信首先要在网络中通过IP地址找到它. IP地址就像我们每个人的名字一样, 是一种特定的标识, IP地址是计算机的标识, 由于其具有唯一性(在同一个网络中, 一个IP地址代表着一台计算机). 应用程序通过IP地址找到这台电脑与之建立通信, 我们知道, 一台计算机中有很多应用程序, 不同的应用程序传输的数据内容以及格式都是各不相同的,
而这些程序是怎么做到区分各自的数据呢? 计算机科学家们想到了一种很好的解决方案, 在计算机中设定了很多个抽象的逻辑端口, 这里端口就好像是信箱一样, 当邮递员来送信的时候将不同人的信件按照信箱上不同房屋的号码一一对应投放进去, 这样人们就可以各自在自己的信箱中收到寄给自己的信件了而不用在一大堆信件中一个一个找了. 端口在计算机通信中的作用于此相类似.
既然是很多计算机之间的通信, 如果每台计算机都按照自己的方式传输数据而没有一种通一的秩序就会大大降低传输效率, 并且通信成本也是非常高昂的.为此有两种通信方式逐渐被大众广泛认可并得以发展. 一种是传输控制协议(Transmission
Control Protocol, TCP), 另一种叫做用户数据报协议(User Datagram Protocol, UDP), 下面分析一下两者之间的共同点和差异.
首先两者均为建立在传输层上的通信协议, 两者达成的目的也是一样的. TCP在传输时首先要通过三路握手过程创建连接, 而UDP只提供数据的不可靠传递,它一但把应用程序发给网络层的数据发送出去,就不保留数据备份(所以UDP有时候也被认为是不可靠的数据报协议).相对UDP来讲,
TCP设定了很多重要的机制保证了它的可靠性和强壮性。它们包括:使用序号,对收到的TCP报文段进行排序以及检测重复的数据;使用校验和来检测报文段的错误;使用确认和计时器来检测和纠正丢包或延时。在绝大部分情况下, TCP被认为是较UDP更安全的.
TCP与UDP的差异 | |||
协议名称 | 是否需要建立连接 | 安全性 | 传输效率 |
TCP | 是 | 高 | 低 |
UDP | 否 | 低 | 高 |
这里TCP较UDP在安全性上面的差异主要表现在:
- 重发丢失的数据包
- 无错误数据传输
- 阻塞/流量控制
- 面向连接(创建连接时三方交握,且连接已创建才作传输。)
/* 实现功能: 输入一段字符发送给另一台计算机, 接收者显示发送者的计算机名称和IP地址以及紧随其后的字符内容 */ import java.net.*; import java.io.*; import java.util.Scanner; class SendDemo { public static void main(String[] args) { try { DatagramSocket ds = new DatagramSocket(); Scanner sc = new Scanner(System.in); System.out.print("Please input a string :"); String str = sc.nextLine(); byte buff[] = str.getBytes(); DatagramPacket dp = new DatagramPacket(buff, buff.length, InetAddress.getByName("192.168.0.101"), 10000); ds.send(dp); sc.close(); ds.close(); } catch(Exception e) { e.printStackTrace(); } } } class ReceDemo { public static void main(String[] args) { try { DatagramSocket ds = new DatagramSocket(10000); byte buff[] = new byte[1024]; DatagramPacket dp = new DatagramPacket(buff, buff.length); ds.receive(dp); String data = new String(dp.getData(), 0, dp.getLength()); String ipName = dp.getAddress().getHostName(); String ipAddress = dp.getAddress().getHostAddress(); System.out.printf("%s(%s) : %s\n", ipName, ipAddress, data); ds.close(); } catch(Exception e) { e.printStackTrace(); } } }
/** 实现功能: 运用TCP协议的Socket和ServerSocket对象实现客户端向服务器端发送一段数据, 服务器对数据进行处理之后发送给客户端, 一个服务器端同时支持多个客户端 应用实例: 网站解密服务, 客户端向服务器端发送经过加密的字符串, 服务器经过处理得到原内容回馈给客户端 */ import java.io.*; import java.util.*; import java.net.*; class TCPClientDemo { public static void main(String[] args) { try { Socket s = new Socket(InetAddress.getByName("192.168.0.101"), 10001); String ip = s.getInetAddress().getHostAddress(); Scanner sc = new Scanner(System.in); BufferedOutputStream bufOut = new BufferedOutputStream(s.getOutputStream()); BufferedInputStream bufIn = new BufferedInputStream(s.getInputStream()); while(true) { String str = sc.nextLine(); bufOut.write(str.getBytes()); bufOut.flush(); if(str.equals("@goodbay")) break; byte buff[] = new byte[1024]; int len = bufIn.read(buff, 0, buff.length); String line = new String(buff, 0, len); System.out.printf("Server : %s\n", line); } s.close(); } catch(IOException e) { System.out.println("field! IOException"); } catch(Exception e) { System.out.println("Exception"); } } } class ServerRunnable implements Runnable { private Socket s; public ServerRunnable(Socket s) { this.s = s; } public void run() { try { String ipAddress = s.getInetAddress().getHostAddress(); String ipName = s.getInetAddress().getHostName(); System.out.printf("%s(%s) is connected.\n", ipName, ipAddress); BufferedInputStream bufIn = new BufferedInputStream(s.getInputStream()); BufferedOutputStream bufOut = new BufferedOutputStream(s.getOutputStream()); String line = null; while(true) { byte buff[] = new byte[1024]; int len = bufIn.read(buff, 0, buff.length); line = new String(buff, 0, len); System.out.printf("%s(%s) : %s", ipName, ipAddress, line); if(line.equals("@goodbay")) break; String enil = new StringBuilder(line).reverse().toString(); bufOut.write(enil.getBytes()); bufOut.flush(); System.out.println(" >>>>replied."); } s.close(); } catch(IOException e) { System.out.println("field! IOException"); } catch(Exception e) { System.out.println("Exception for run()"); } finally { } } } class TCPServerDemo { public static void main(String[] args) { try { ServerSocket ss = new ServerSocket(10001); while(true) { Socket s = ss.accept(); new Thread(new ServerRunnable(s)).start(); } } catch(IOException e) { System.out.println("Server field. IO"); } catch(Exception e) { System.out.println("Exception for Server."); } } }
/* 实现功能: 实现客户端向服务器端发送一张图片 服务器端收到图片后向客户端发送一段视频 客户端收到视频后关闭 */ import java.util.*; import java.io.*; import java.net.*; class ImageTransClient { public static void main(String[] args) { try { Socket s = new Socket(InetAddress.getByName("192.168.0.101"), 10003); File image = new File("C:\\Users\\苏诚\\Pictures\\图片收集\\鸣人20130224113216.jpg"); File video = new File("C:\\Users\\苏诚\\javadoc\\Test\\buffer\\testTransVideo.avi"); FileOutputStream output = new FileOutputStream(video, false); FileInputStream input = new FileInputStream(image); if(!image.exists()) { System.out.println("Error for URL of the Image."); return; } OutputStream bufOut = s.getOutputStream(); byte buff[] = new byte[1024]; int len; while((len=input.read(buff)) != -1) { bufOut.write(buff, 0, len); } input.close(); s.shutdownOutput(); InputStream bufIn = s.getInputStream(); while((len=bufIn.read(buff)) != -1) { output.write(buff, 0, len); } output.flush(); // bufIn.close(); output.close(); System.out.println("Video transfer is complete."); s.close(); } catch(FileNotFoundException e) { e.printStackTrace(); } catch(IOException e) { e.printStackTrace(); } catch(Exception e) { e.printStackTrace(); System.out.println("Field for Client."); } } } class ImageTransServer { public static void main(String[] args) { try { ServerSocket ss = new ServerSocket(10003); Socket s = ss.accept(); String ipName = s.getInetAddress().getHostName(); String ipAddress = s.getInetAddress().getHostAddress(); System.out.printf("%s(%s) is connected.\n", ipName, ipAddress); File image = new File("C:\\Users\\苏诚\\javadoc\\Test\\buffer\\testTransImage.jpg"); File video = new File("D:\\Documents\\heima\\黑马视频教程\\张孝祥_交通灯管理系统\\破解之一_交通灯管理系统视频教程_编写Road类中模拟汽车上路的代码\\07.avi"); FileOutputStream output = new FileOutputStream(image, false); FileInputStream input = new FileInputStream(video); /* if(!image.exists()) { output = new FileOutputStream(image); } else { return; } if(video.exists()) { input = new FileInputStream(video); } else { return; } */ InputStream bufIn = s.getInputStream(); byte buff[] = new byte[1024]; int len; while((len=bufIn.read(buff)) != -1) { output.write(buff, 0, len); } output.flush(); output.close(); System.out.println("Photo transfer is complete."); OutputStream bufOut = s.getOutputStream(); while((len=input.read(buff)) != -1) { bufOut.write(buff, 0, len); } bufOut.flush(); input.close(); s.close(); ss.close(); } catch(Exception e) { System.out.println("Field for Server."); } } }