套接字是java提供一套进行网络通信的API---TCP/UDP;
ISO七层模型
物理层 、数据链路层 、传输层-IP、 网络层-UDP/TCP 、会话层 、 表示层、 应用层 ---HTTP FTP POP3 SMTP...
IP地址:在网络中标识计算机地址的---IPv4---用四组整数(0-255)标识一个IP地址---123.125.43.11---IPv6
端口号: 用于指定接收或者发送消息的端口---0-65535---0-1024被计算机内部占用
UDP
基于流的,不需要建立连接,不可靠,会对数据进行封包,每个包是64k大小,传输效率是比较高。例如直播
java提供了一套套接字用于UDP通信:
1.InetSocketAddress("IP地址",端口号):表示IP地址和端口号;
2.DatgramSocket():用来发送和接收数据包的套接字;
3.DatagramPacket(byte[] buf, int length, SocketAddress address):用来对数据封包,以便传输;
发送端基本步骤:
1.创建发送数据套接字对象;
2.创建目的地的IP地址和发送端口;
3.将数据封包;
4.发送(send(DatagramPacket dp)方法);
5.关闭套接字(close());
接收端基本步骤:
1.创建接收数据的套接字对象并绑定接收数据的端口;
2.创建数据封包用来储存数据;
3.接收数据(receive(DatagramPacket dp));
4.关闭套接字(close());
1 import java.net.DatagramPacket; 2 import java.net.DatagramSocket; 3 import java.net.InetSocketAddress; 4 import java.util.Scanner; 5 6 public class UDPChatDemo { 7 8 public static void main(String[] args) { 9 10 new Thread(new Sender()).start(); 11 new Thread(new Receiver()).start(); 12 } 13 14 } 15 16 // 发送端 17 class Sender implements Runnable { 18 19 @SuppressWarnings("resource") 20 @Override 21 public void run() { 22 23 try { 24 // 准备套接字对象 25 DatagramSocket ds = new DatagramSocket(); 26 27 // 创建一个地址对象 28 InetSocketAddress isa = new InetSocketAddress("localhost", 9527); 29 30 // 从控制台来获取数据 31 Scanner s = new Scanner(System.in); 32 33 while (true) { 34 String msg = s.nextLine(); 35 36 // 将数据封包 37 DatagramPacket dp = new DatagramPacket(msg.getBytes(), msg.getBytes().length, isa); 38 39 // 发送数据 40 ds.send(dp); 41 42 // 判断这个语句是否是exit 43 if (msg == "exit" || msg != null && msg.equals("exit")) { 44 break; 45 } 46 } 47 48 } catch (Exception e) { 49 e.printStackTrace(); 50 } 51 52 } 53 54 } 55 56 class Receiver implements Runnable { 57 58 @SuppressWarnings("resource") 59 @Override 60 public void run() { 61 62 try { 63 // 准备套接字对象,绑定端口号 64 DatagramSocket ds = new DatagramSocket(9527); 65 66 // 准备数据包 67 DatagramPacket dp = new DatagramPacket(new byte[1024], 1024); 68 69 while (true) { 70 71 // 接收数据 72 ds.receive(dp); 73 74 // 获取数据 75 String msg = new String(dp.getData(), 0, dp.getLength()); 76 if (msg == "exit" || msg != null && msg.equals("exit")) { 77 break; 78 } 79 80 // 获取地址 81 System.out.print(dp.getAddress() + ":"); 82 System.out.println(msg); 83 } 84 85 } catch (Exception e) { 86 e.printStackTrace(); 87 } 88 89 } 90 91 }
TCP
基于流的,需要建立连接,经过了三次握手,理论上不限制数据的大小,传输速率比较低。例如文件的传输
java提供的套接字:
Socket:客户端套接字
ServerSocket:服务器端套接字
客户端基本步骤:
1.创建客户端套接字对象;
2.发起连接,并绑定连接地址;
3.获取输出流,写出数据;
4.通知服务器端数据写出完毕;
5.关闭套接字
1 import java.io.InputStream; 2 import java.io.OutputStream; 3 import java.net.InetSocketAddress; 4 import java.net.Socket; 5 6 public class TCPClientDemo2 { 7 8 public static void main(String[] args) throws Exception { 9 10 // 创建客户端的套接字 11 Socket s = new Socket(); 12 13 // 发起连接,绑定端口号 14 s.connect(new InetSocketAddress("localhost", 8980)); 15 16 // 获取输出流 17 OutputStream out = s.getOutputStream(); 18 19 // 写出数据 20 out.write("我来啦啦啦~~~".getBytes()); 21 22 // 关闭输出流 23 s.shutdownOutput(); 24 25 // 获取输入流 26 InputStream in = s.getInputStream(); 27 28 // 读取数据 29 byte[] bs = new byte[1024]; 30 int len = -1; 31 while ((len = in.read(bs)) != -1) { 32 System.out.println(new String(bs, 0, len)); 33 } 34 35 // 通知服务器端数据已经读取完毕 36 s.shutdownInput(); 37 38 // 关闭套接字 39 s.close(); 40 41 } 42 43 }
服务器端基本步骤:
1. 创建服务器端套接字,绑定端口号
2. 接受连接,获取到一个Socket对象
3. 获取输入流,读取数据
4. 通知客户端数据读取完毕
5. 关闭套接字
1 import java.io.InputStream; 2 import java.net.ServerSocket; 3 import java.net.Socket; 4 5 public class TCPServerDemo { 6 7 public static void main(String[] args) throws Exception { 8 9 // 创建一个服务器端套接字对象---绑定端口号 10 ServerSocket ss = new ServerSocket(9999); 11 12 // 接受连接 13 Socket s = ss.accept(); 14 15 // 获取一个输入流 16 InputStream is = s.getInputStream(); 17 18 // 读取数据 19 byte[] bs = new byte[1024]; 20 int len = -1; 21 while ((len = is.read(bs)) != -1) { 22 System.out.println(new String(bs, 0, len)); 23 } 24 25 // 通知客户端数据读取完毕 26 s.shutdownInput(); 27 28 // 关闭套接字 29 s.close(); 30 ss.close(); 31 32 } 33 34 }
注意:receive/connect/accept/read/write都会产生阻塞