websocket百万级连接java:张小飞的Java之路,第四十七章
写在前面:
视频是什么东西,有看文档精彩吗?
视频是什么东西,有看文档速度快吗?
视频是什么东西,有看文档效率高吗?
诸小亮:讲解了一些基础知识后,我们正是学习Socket
张小飞:Sokcet 是啥?
诸小亮:Socket:Java中为网络通信提供的一种机制,专业称:套接字
两个电脑进行通信时,数据在两个Sokcet之间通过IO传输
张小飞:具体该如何使用呢?
诸小亮:Java中使用 Sokcet 有两种方式——UDP和TCP
1. UDP通信诸小亮:我们先看UDP
不需要建立连接,封装数据包,大小限制在64K以内 不可靠,安全性差,但速度快(就是发,对方是否接到,咱不管,比如:村里的喇叭)
张小飞:还是演示一下吧
1.1. 入门诸小亮:没问题,首先是——接收端,看下面的代码
import java.io.IOException;import java.net.DatagramPacket;import java.net.DatagramSocket;/*** 接收端*/public class Receive { public static void main(String[] args) throws IOException { //1. 创建Socket,监听10000端口 DatagramSocket socket = new DatagramSocket(10000); //2. 通过数据包接收数据 byte[] arr = new byte[1024]; //3. 创建 DatagramPacket 对象,用来接收数据 DatagramPacket packet = new DatagramPacket(arr, arr.length); System.out.println("UDP接收端,准备接收数据。。。。。。"); //3.1 调用receive方法,如果收不到数据,程序会阻塞(也就是程序会停在这里,直到有数据) socket.receive(packet); //4. 通过DatagramPacket对象,解析收到的数据 String ip = packet.getAddress().getHostAddress(); int port = packet.getPort(); byte[] data = packet.getData(); //5. 转换成String String msg = new String(data,0, packet.getLength()); System.out.println("发送者IP:" ip); System.out.println("发送者端口:" port); System.out.println("消息内容:" msg); //6. 关闭Socket socket.close(); }}
张小飞:有了接收端,想必还有发送端把
诸小亮:那是必须的,下面就是发送端的代码
import java.io.IOException;import java.net.DatagramPacket;import java.net.DatagramSocket;import java.net.InetAddress;public class Send { public static void main(String[] args) throws IOException { //1. 创建Socket,监听5000端口 DatagramSocket sendSocket = new DatagramSocket(5000); //如果不指定端口,会随机开启一个端口进行数据发送// DatagramSocket sendSocket = new DatagramSocket(); //2. 通过数据包封装数据 String msg = "亚瑟提着大宝剑冲过来了"; byte[] data = msg.getBytes(); //需要ip和端口号 DatagramPacket packet = new DatagramPacket(data, 0, data.length, InetAddress.getLocalHost(),10000); //3. 发送数据 System.out.println("UDP发送端,发送数据。。。。"); sendSocket.send(packet); //4. 关闭Socket sendSocket.close(); }}
诸小亮:先启动接收端,再启动发送端,结果:
1.2. 群聊诸小亮:其实使用 UDP 可以实现群聊的功能
张小飞:哦?怎么实现?
诸小亮:UDP模式下,可以在局域网中发送广播消息,局域网中的每个电脑都能收到消息
IP地址中每个网段都有自己的广播地址,本机IP:192.168.31.173则 192.168.31 网段的广播地址是 192.168.31.255
张小飞:那,具体应该如何实现呢?
诸小亮:把上面的代码稍微改改就行了
1.2.1. 接收端因为 receive 方法会阻塞,所以可以把 socket.receive(packet); 放到 while 循环中,一直接收消息
import java.io.IOException;import java.net.DatagramPacket;import java.net.DatagramSocket;public class Receive { public static void main(String[] args) throws IOException { //1. 创建Socket,监听10000端口 DatagramSocket socket = new DatagramSocket(10000); System.out.println("UDP接收端,准备接收数据。。。。。。"); while (true){ //2. 通过数据包接收数据 byte[] arr = new byte[1024]; DatagramPacket packet = new DatagramPacket(arr, arr.length); //receive方法,如果收不到数据会阻塞,也就是程序会停在这里直到有数据 socket.receive(packet); //3. 通过DatagramPacket对象,解析收到的数据 String ip = packet.getAddress().getHostAddress(); byte[] data = packet.getData(); //转换成String String msg = new String(data,0, packet.getLength()); System.out.println(ip ":" msg); } //4. 一直运行接收消息,所以不再关闭Socket// socket.close(); }}
1.2.2. 发送端
发送端,接收用户的输入,然后发送广播
import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.net.DatagramPacket;import java.net.DatagramSocket;import java.net.InetAddress;public class Send { public static void main(String[] args) throws IOException { //1. 创建Socket,监听5000端口 DatagramSocket sendSocket = new DatagramSocket(5000); //2. 接收用户输入 System.out.println("开始接收用户输入。。。。。。"); BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in)); String line = null; while((line=bufr.readLine())!=null){ byte[] buf = line.getBytes(); DatagramPacket dp = new DatagramPacket(buf,buf.length, InetAddress.getByName("192.168.31.255"),10000); sendSocket.send(dp); if("886".equals(line)) break; } //4. 关闭Socket sendSocket.close(); }}
1.2.3. 结果
张小飞:您不是说还有 TPC 通信吗?这个怎么用?
诸小亮:TPC通信就比UDP要麻烦一些了
需要两台电脑建立连接,形成数据通道,在连接中进行大数据量传输因为必须建立连接,所以效率低,但安全性高,比如:打电话
张小飞:这么说,可以做一对一通信?
诸小亮:是的
2.1.1. 基本演示诸小亮:TCP通信需要创建连接,分为客户端(Socket)、服务端(ServerSocket)
/*** 客户端*/public static void main(String[] args) throws IOException { //1. 创建Socket对象,指定目的IP和端口,用于创建连接 Socket socket = new Socket("127.0.0.1", 10000); //2. 发送数据 System.out.println("客户端发送数据。。。。。。"); OutputStream out = socket.getOutputStream(); out.write("亚瑟提着大宝剑冲过来了".getBytes()); //3. 关闭Socket socket.close();}
张小飞:这也不麻烦啊,比 UDP 简单多了
诸小亮:客户端是很简单,麻烦的地方在服务端,比如:
/*** 服务端*/public static void main(String[] args) throws IOException { //1. 创建ServerSocket,指定监听10000端口 ServerSocket serverSocket = new ServerSocket(10000); System.out.println("等待客户端连接。。。。。。"); //2. 获取Socket对象,如果能够获取到,说明连接成功 //注意:accept 方法会阻塞,直到有连接过来 Socket client = serverSocket.accept(); String ip = client.getInetAddress().getHostAddress(); int port = client.getPort(); System.out.println(ip "--" port ":连接成功。。。。。。"); //3. 通过客户端的IO流,获取数据 InputStream in = client.getInputStream(); byte[] arr = new byte[1024]; int len = in.read(arr); String msg = new String(arr,0,len); System.out.println(msg); //3.关闭资源 client.close(); serverSocket.close();}
诸小亮:先运行服务端,再运行客户端,结果:
2.1.2. 2. 客户端和服务端互相通信张小飞:上面的代码服务端只能被动的接收数据啊,能不能让它们互相通信?
诸小亮:满足你
/*** 客户端*/public static void main(String[] args) throws IOException { //1. 创建Socket对象,指定目的IP和端口 Socket socket = new Socket("127.0.0.1", 10000); //2. 发送数据 System.out.println("客户端发送数据。。。。。。"); OutputStream out = socket.getOutputStream(); out.write("亚瑟提着大宝剑冲过来了".getBytes()); //3. 拿到InputStream,用于获取服务端返回的数据 InputStream in = socket.getInputStream(); byte[] arr = new byte[1024]; int len = in.read(arr); String msg = new String(arr,0,len); System.out.println("服务端返回:" msg); //4. 关闭Socket socket.close();}
/*** 服务端*/public static void main(String[] args) throws IOException { //1. 创建ServerSocket,指定监听10000端口 ServerSocket serverSocket = new ServerSocket(10000); System.out.println("等待客户端连接。。。。。。"); //2. 获取Socket对象,能够获取到,说明连接成功,accept会阻塞,直到新的连接过来 Socket client = serverSocket.accept(); String ip = client.getInetAddress().getHostAddress(); int port = client.getPort(); System.out.println(ip "--" port ":连接成功。。。。。。"); //通过客户端的IO流,获取数据 InputStream in = client.getInputStream(); byte[] arr = new byte[1024]; int len = in.read(arr); String msg = new String(arr,0,len); System.out.println(msg); //3. 返回信息给客户端 System.out.println("服务端端发送数据。。。。。。"); OutputStream out = client.getOutputStream(); out.write("吕布大招断路。。。。".getBytes()); //4.关闭资源 client.close(); serverSocket.close();}
先运行服务端,再运行客户端,结果:
张小飞:额。。。。,您这样确实是互相通信,不过,能不能做成QQ聊天那样子的?
诸小亮:也是可以的
2.1.3. 练习:一对一聊天2.1.3.1. 客户端import java.io.*;import java.net.Socket;public class Client { public static void main(String[] args) throws IOException { //1. 创建Socket对象,指定目的IP和端口 Socket socket = new Socket("127.0.0.1", 20000); //开启一个守护线程,用于接收用户输入 receiveUserInput(socket); //接收服务端发送的数据 InputStream in = socket.getInputStream(); while (true){ byte[] arr = new byte[1024]; int len = in.read(arr); if(len == -1){//-1:表示结束 break; } String msg = new String(arr,0,len); System.out.println("server:" msg); //如果Server 发送过来的是 886,跳出循环,结束通讯 if("886".equals(msg)){ break; } } //4. 关闭Socket socket.close(); } private static void receiveUserInput(Socket socket) { Thread t = new Thread(new Runnable() { @Override public void run() { try{ //2. 接收用户输入,发送给Server System.out.println("开始接收用户输入。。。。。。"); BufferedReader reader = new BufferedReader( new InputStreamReader(System.in)); OutputStream out = socket.getOutputStream(); String line = null; while(true){ line = reader.readLine(); out.write(line.getBytes()); //如果输入886,跳出循环,结束通讯 if("886".equals(line)) break; } }catch (Exception e){ } } }); //设置为守护线程,主线程结束后,守护线程也结束 t.setDaemon(true); t.start(); }}
2.1.3.2. 服务端
import java.io.*;import java.net.ServerSocket;import java.net.Socket;public class Server { public static void main(String[] args) throws IOException { //1. 创建ServerSocket,指定监听10000端口 ServerSocket serverSocket = new ServerSocket(20000); //2. 获取客户端连接,能够获取到,说明连接成功,accept会阻塞,直到新的连接过来 System.out.println("等待客户端连接。。。。。。"); Socket client = serverSocket.accept(); String ip = client.getInetAddress().getHostAddress(); System.out.println(ip " 连接成功。。。。。。"); //开启一个守护线程,用于接收用户输入 receiveUserInput(client); //通过客户端的IO流,获取数据 InputStream in = client.getInputStream(); while (true){ byte[] arr = new byte[1024]; int len = in.read(arr); if(len == -1){//-1表示结束 break; } String msg = new String(arr,0,len); System.out.println("client:" msg); //如果客户端发送的是886,跳出循环,结束通讯 if("886".equals(msg)){ break; } } //4.关闭资源 client.close(); serverSocket.close(); } private static void receiveUserInput(Socket client) { Thread t = new Thread(new Runnable() { @Override public void run() { try{ //2. 接收用户输入,发送给client System.out.println("开始接收用户输入。。。。。。"); //接收用户输入 BufferedReader bufr = new BufferedReader( new InputStreamReader(System.in)); String line = null; //给客户端发送数据 OutputStream out = client.getOutputStream(); while(true){ line = bufr.readLine(); out.write(line.getBytes()); //如果给客户端发送的是886,跳出循环,结束通讯 if("886".equals(line)) break; } }catch (Exception e){ } } }); //设置为守护线程,主线程结束后,守护线程也结束 t.setDaemon(true); t.start(); }}
2.1.3.3. 3. 结果
上面代码,客户端和服务端,分别在局域网中的不同机器上运行
先运行 Server,再运行 Client
- 12-03干洗店把大衣洗褪色谁的责任,滨州市民干洗鞋子严重褪色
- 01-08祝孩子高考金榜题名简短语:家长们居然用这几种方式保佑孩子金榜题名
- 12-24阿莫西林 要认清 只对6种疾病有效 这些内容你可能还不知道
- 01-13最美的风景在路上济南的冬天:从浓艳鲜亮的夏到金风玉露的秋
- 11-05防摔好看功能型手机壳:手感.功能.防摔.磁吸.质感
- 01-04詹姆斯11640次打铁仅排现役第二:詹姆斯11640次打铁仅排现役第二
- 01-29快速克服考试紧张的方法 如何克服考试紧张的六个有效方法详解
- 01-02广州玩游艇地方有哪些景点?广州富豪介绍,骑马游艇出海
- 12-26黄口中心小学生升国旗仪式:多图,向国旗敬礼民众镇中小学举行大型升旗仪式活动
- 02-06仙剑最后李逍遥到什么高度了?你知道为什么仙剑中蜀山剑圣没有帮李逍遥他们制止拜月吗
- 03-09win11笔记本如何禁用wifi?如何在Win7,Win8Win10笔记本电脑上启用WiFi
- 04-15有史以来最强大的猛兽,还想着,滑铲
- 01-02盯盯拍s50和华为车载智慧屏 与华为手机更配盯盯拍智慧后视镜S5
- 11-14猫如何理解铲屎行为?有损,猫格的几种行为
- 02-24情侣日常生活画手绘:各种情侣照,单人照全家福都可以画成美美的卡通手绘
- 03-09三亚导游斥责游客没购物海口处理 海南三亚游客租车被骗
热门
推荐
- 1春季脸部皮肤过敏怎么治疗186
- 22019年宾馆管理“安全生产月”活动总结306
- 3演讲时什么站姿比较好_演讲时的手势370
- 4二年级作文附评语261
- 5驰名商标如何进行保护165
- 6在工作中为什么遭受职场性别歧视224
- 7微信头像美女图片高清大图256
- 8系统重装不能联网怎么办425