1、
UDP
将数据及源和目的封装成数据包,不需要建立连接
每个数据包的大小在限制在64k内
因无连接,是不可靠协议
不需要建立连接,速度快
TCP
建立连接,形成传输数据的通道
在连接中进行大数据量传输
通过三次握手完成连接,是可靠协议
必须建立连接,效率低
Socket
为网络服务提供的一种机制
通信的两端都有Socket
网络通信其实就是Socket间的通信
数据在两个Socket间通过IO传输
IP地址
网络中设备的标识
不易记忆,可用主机名
本地回环地址:127.0.0.1,主机名:localhost
端口号
用于标识进程的逻辑地址,不同进程的标识
有效端口:0-65535,其中0-1024系统使用或保留端口
传输协议
通讯的规则
常见协议TCP,UDP
2、IP地址
1 package learn; 2 3 import java.io.IOException; 4 import java.net.InetAddress; 5 6 public class IPDemo { 7 public static void main(String[] args) throws IOException{ 8 // InetAddress i = InetAddress.getLocalHost(); 9 // System.out.println(i.toString()); 10 // System.out.println("address:"+i.getHostAddress()); 11 // System.out.println("name"+i.getHostName()); 12 //任意一台注意提取地址 13 InetAddress ia = InetAddress.getByName("192.168.1.103"); 14 System.out.println("address:"+ia.getHostAddress()); 15 System.out.println("name"+ia.getHostName()); 16 } 17 }
运行结果
3、UDP
3.1、UDP发送接收
3.1.1、UDP发送
1 package learn; 2 3 import java.io.IOException; 4 import java.net.DatagramPacket; 5 import java.net.DatagramSocket; 6 import java.net.InetAddress; 7 import java.net.*; 8 9 /* 10 * 通过UDP传输方式将一段文字数据发送出去 11 * 思路 12 * 1、建立udpsocket服务 13 * 2、提供数据,并将数据封装带数据包中 14 * 3、通过socket服务的发送功能,将数据包发送出去 15 * 4、关闭资源 16 * */ 17 18 public class UdpSend { 19 public static void main(String[] args) throws Exception{ 20 //1、创建udp服务。通过DatagramSocket对象 21 DatagramSocket ds = new DatagramSocket(); 22 //2、确定数据,封装数据包 23 byte[] buf="udplaile".getBytes(); 24 //处理数据的地址,端口 25 DatagramPacket dp = new DatagramPacket(buf,buf.length,InetAddress.getByName("192.168.1.103"),10000); 26 //3、通过socket服务,将已有的数据包发送出去,通过send方法 27 ds.send(dp); 28 //4、关闭资源 29 ds.close(); 30 31 } 32 }
3.1.2、UDP接收
1 package learn; 2 3 import java.net.DatagramPacket; 4 import java.net.DatagramSocket; 5 6 /*需求:定义一个应用程序,用于接收UDP协议传输的数据并处理的 7 * 定义接收端 8 * 思路 9 * 1、定义Udpsocket服务,通常会监听一个端口,其实就是给这个接受网络应用程序定义数字标识 10 * 方便与明确哪些数据过来该应用程序可以处理 11 * 2、定义一个数据包。因为要存储接收到的字节数据,因为数据包对象中有更多功能可以提取字节数据中的不同数据信息 12 * 3、通过socket服务的receive方法将受到的数据存入已定义好的数据包中 13 * 4、通过数据包对象的特有功能,将这些不同的数据取出,打印在控制台上 14 * 5、关闭资源 15 * 16 * */ 17 public class UdpRece { 18 public static void main(String[] args) throws Exception{ 19 //1、创建udpsocket,建立端点 20 DatagramSocket ds = new DatagramSocket(10000); 21 //2、定义数据包,用于存储数据 22 byte[] buf = new byte[1024]; 23 DatagramPacket dp = new DatagramPacket(buf,buf.length); 24 //3、通过服务的receive方法将收到的数据存入数据包中 25 ds.receive(dp); 26 //4、通过数据包的方法获取其中的数据 27 String ip = dp.getAddress().getHostAddress(); 28 29 String data = new String(dp.getData(),0,dp.getLength()); 30 int port = dp.getPort(); 31 System.out.println(ip+":"+data+":"+port); 32 //5.关闭资源 33 ds.close(); 34 } 35 }
3.2、模拟chat
1 package learn; 2 3 import java.io.BufferedReader; 4 import java.io.IOException; 5 import java.io.InputStreamReader; 6 import java.net.DatagramPacket; 7 import java.net.DatagramSocket; 8 import java.net.InetAddress; 9 10 //发送端 11 class Send implements Runnable 12 { 13 //用哪个socket不确定,故构造时传指定Socket 14 private DatagramSocket ds; 15 //构造函数,用于接收Socket对象 16 Send(DatagramSocket ds) 17 { 18 this.ds=ds; 19 } 20 public void run() 21 { 22 23 try 24 { 25 //发送,读键盘,转换流 26 BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in)); 27 String line = null; 28 //读取 29 while((line = bufr.readLine())!=null) 30 { 31 if("886".equals(line)) 32 break; 33 //字符串转字节数组 34 byte[] buf = line.getBytes(); 35 //字节数组存入数据包,定义要发送的主机和端口号 36 DatagramPacket dp = 37 new DatagramPacket(buf,buf.length,InetAddress.getByName("192.168.1.103"),10002); 38 //数据包丢入socket 39 ds.send(dp); 40 41 } 42 //关闭发送 43 ds.close(); 44 } 45 catch(Exception e) 46 { 47 throw new RuntimeException("发送端失败"); 48 } 49 } 50 } 51 //接收端 52 class Rece implements Runnable 53 { 54 private DatagramSocket ds; 55 //构造函数,用于接收Socket对象 56 Rece(DatagramSocket ds) 57 { 58 this.ds=ds; 59 } 60 public void run() 61 { 62 try 63 { 64 //接收端做好随时接收的准备,故无限循环 65 while(true) 66 { 67 // 将接收到的数据存储到定义好的数据包中 68 byte[] buf = new byte[1024]; 69 DatagramPacket dp = new DatagramPacket(buf,buf.length); 70 //数据包丢入socket服务中 71 ds.receive(dp); 72 //获取数据中主机地址和数据长度 73 String ip = dp.getAddress().getHostAddress(); 74 String data = new String(dp.getData(),0,dp.getLength()); 75 //输出数据 76 System.out.println(ip+".."+data); 77 } 78 } 79 catch(Exception e) 80 { 81 throw new RuntimeException("接收端失败"); 82 } 83 } 84 } 85 public class ChatDemo { 86 public static void main(String[] args) throws Exception { 87 //先有Socket 88 DatagramSocket sendSocket = new DatagramSocket(); 89 DatagramSocket receSocket = new DatagramSocket(10002); 90 //线程启动 91 new Thread(new Send(sendSocket)).start(); 92 new Thread(new Rece(receSocket)).start(); 93 } 94 }
4、TCP
4.1、端点接收数据,打印在控制台
客户端
通过查阅socket对象,发现在该对象建立时就可以连接指定的主机,
因为tcp是面向连接的,所以在建立socket服务时就要有服务端存在并连接成功,形成通路后再该通道进行数据的传输
步骤
* 1、创建socket服务,并指定要连接的主机和端口
* 2、获取输出流,并发送
* 3、关闭服务
* */
*服务端:
步骤
* 1、建立服务端的socket服务,ServerSocket();
* 2、获取连接过来的客户端对象
* 通过ServerSocket的accept方法,没有连接就会等,所以这个方法阻塞式的
* 3、客户端如果发过来数据,那么服务端要使用对应的客户端对象,并获取到该客户端对象的读取流来读取发过来的数据
* 并打印在控制台
* 4、关闭服务端(可选)
1 package learn; 2 3 import java.io.IOException; 4 import java.io.InputStream; 5 import java.io.OutputStream; 6 import java.net.ServerSocket; 7 import java.net.Socket; 8 9 10 11 class Tcpclient 12 { 13 public static void main(String[] args) throws IOException{ 14 //创建客户端的socket服务,指定目的主机和端口 15 Socket s = new Socket("192.168.1.103",10003); 16 //为了发送数据,应该选取socket流中的输出流 17 OutputStream out = s.getOutputStream(); 18 out.write("tcp ge men laile".getBytes()); 19 s.close(); 20 } 21 } 22 23 /* 24 * 需求:定义端点接收数据并打印在控制台上 25 26 * */ 27 class Server 28 { 29 public static void main(String[] args)throws IOException { 30 //建立服务端的socket服务,并监听一个端口 31 ServerSocket ss = new ServerSocket(1003); 32 //通过accept方法获取连接过来的客户端对象 33 Socket s = ss.accept(); 34 35 String ip = s.getInetAddress().getHostAddress(); 36 System.out.println(ip+"..connected"); 37 //获取客户端发送过来的数据,那么要使用客户端对象的读取流来读取数据 38 InputStream in = s.getInputStream(); 39 40 //读数据 41 byte[] buf = new byte[1024]; 42 int len = in.read(buf); 43 System.out.println(new String(buf,0,len)); 44 s.close(); 45 ss.close(); 46 } 47 }
4.1.1、TCP上传文件
客户端
* 1、服务端点
* 2、读取客户端已有的图片数据
* 3、通过socket输出流将数据发给服务端
* 4、读取服务端反馈信息
* 5、关闭
服务器端
* 这个服务端有个局限性,当A客户端连接上以后,被服务端获取到,服务端执行具体流程
* 这时B客户端连接,只有等待
* 因为服务端还没有处理完A客户端的请求,还有循环回来执行下次accept方法,所以暂时获取不到B客户端对象
* 那么为了可以让多个客户端同时并发访问服务器
* 那么服务端最好就是将每个客户端封装到一个担负的线程中,这样就可以同时处理多个客户端请求
*
* 如何定义线程
* 只要明确了每一个客户端要在服务端执行的代码即可,将该代码存入run方法中
4.2、TCP并发上传图片
1 package learn2; 2 /* 3 * tcp并发上传图片 4 */ 5 import java.io.*; 6 import java.net.*; 7 //客户端 8 class PicClient 9 { 10 public static void main(String[] args)throws Exception 11 { 12 //args为传入的文件的路径 13 if(args.length!=1) 14 { 15 System.out.println("请选择一个jpg格式的图片"); 16 return ; 17 } 18 19 //dos命令行中传入的路径 20 File file = new File(args[0]); 21 //判断文件是否存在和是否是文件 22 if(!(file.exists() && file.isFile())) 23 { 24 System.out.println("该文件有问题,要么不存在,要么不是文件"); 25 return ; 26 27 } 28 //判断是否是jpg图片 29 if(!file.getName().endsWith(".jpg")) 30 { 31 System.out.println("图片格式错误,请重新选择"); 32 return ; 33 } 34 //过5M的图片都不要 35 if(file.length()>1024*1024*5) 36 { 37 System.out.println("文件过大。。。没安好心。"); 38 return ; 39 } 40 41 //创建Socket流 42 Socket s = new Socket("192.168.1.3",10008); 43 44 //建立读取流,读取图片文件 45 FileInputStream fis = new FileInputStream(file); 46 //建立Socket的输出流,用于给服务端发送数据 47 OutputStream out = s.getOutputStream(); 48 //定义数组 49 byte[] buf = new byte[1024]; 50 int len = 0; 51 //从流中读完数据,存入数组 52 while((len=fis.read(buf))!=-1) 53 { 54 //数组中的数据写入输出流 55 out.write(buf,0,len); 56 } 57 58 //防止等待的结束标记 59 s.shutdownOutput(); 60 //读取服务器返回的数据 61 InputStream in = s.getInputStream(); 62 63 byte[] bufIn = new byte[1024]; 64 int num = in.read(bufIn); 65 System.out.println(new String(bufIn,0,num)); 66 //关闭资源 67 fis.close(); 68 s.close(); 69 } 70 } 71 72 //并发多线程 73 class PicThread implements Runnable 74 { 75 private Socket s; 76 PicThread(Socket s) 77 { 78 this.s = s; 79 } 80 public void run() 81 { 82 //定义一个计数器,给接收到的照片起名字 83 int count = 1; 84 //获取客户端的IP地址 85 String ip = s.getInetAddress().getHostAddress(); 86 try 87 { 88 //打印连接上的客户端的IP地址 89 System.out.println(ip+"-------连接"); 90 InputStream in = s.getInputStream(); 91 File dir = new File("e:\Tcp传输图片"); 92 File file = new File(dir,ip+"("+(count)+")"+".jpg"); 93 //如果要存入的名称已经存在了那么就把count自增,再设置新的名字。 94 while(file.exists()) 95 file = new File(dir,ip+"("+(count++)+")"+".jpg"); 96 97 FileOutputStream fos = new FileOutputStream(file); 98 byte[] buf = new byte[1024]; 99 int len = 0; 100 while((len=in.read(buf))!=-1) 101 { 102 fos.write(buf,0,len); 103 } 104 OutputStream out = s.getOutputStream(); 105 106 out.write("上传成功!".getBytes()); 107 //关闭资源 108 fos.close(); 109 s.close(); 110 } 111 catch (Exception e) 112 { 113 throw new RuntimeException(ip+"上传失败"); 114 } 115 } 116 } 117 118 //服务端 119 class PicServer 120 { 121 public static void main(String[] args) throws Exception 122 { 123 //监听端口 124 ServerSocket ss = new ServerSocket(10008); 125 126 while(true) 127 { 128 //获取连接到服务端的客户端对象 129 Socket s = ss.accept(); 130 new Thread(new PicThread(s)).start(); 131 } 132 //一直处于接收状态,所以不关闭资源 133 //ss.close(); 134 } 135 }
5、URL
是一个浏览器地址封装类
URI范围比URL大
常用方法
String getFile() :获取此 URL 的文件名。
String getHost() :获取此 URL 的主机名(如果适用)。
String getPath() :获取此 URL 的路径部分。
int getPort() :获取此 URL 的端口号。
String getProtocol() :获取此 URL 的协议名称。
String getQuery() :获取此 URL 的查询部
6、小知识
InetSocketAddress类封装的是(IP地址+端口)
ServerSocket(int port, int backlog)
backlog队列的最大长度,一般50
7、域名解析