Socket编程
2021/12/28 11:08:07
本文主要是介绍Socket编程,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
文章目录
- 一、Socketbc编程
- 1.IP和端口号(组成网络)
- 2.Tcp与UDP概念
- 3.Socket编程原理
- 4.代码
- 5.UDP程序的原理
- 6.主要类的方法
- 7、代码具体实现
- 8、UDP对聊
- 总结
一、Socketbc编程
public class ServerSocket
extends Object
implements Closeable
这个类实现了服务器套接字。 服务器套接字等待通过网络进入的请求。 它根据该请求执行一些操作,然后可能将结果返回给请求者。
服务器套接字的实际工作由SocketImpl类的实例执行。 应用程序可以更改创建套接字实现的套接字工厂,以配置自己创建适合本地防火墙的套接字。
1.IP和端口号(组成网络)
IP(internet Protocol),网络之间的互联协议,IP(加子网掩码)是区分不同计算机的唯一标识
端口号是计算机的逻辑通信接口,不同的应用程序用不同的端口号,网络应用程序的区分标识
端口号一般是两个字节(16给bit 65536)
1、公认端口
第一类:公认端口(Well Known Ports):从0到1023,它们紧密绑定(binding)于一些服务。通常这些端口的通讯明确表明了某种服务的协议,例如:80端口实际上总是HTTP通讯。 21 ftp 22 ssh(security shell) 443 https …
2、注册端口 (1024-49151)
第一类:公认端口(Well Known Ports):从0到1023,它们紧密绑定(binding)于一些服务。通常这些端口的通讯明确表明了某种服务的协议,例如:80端口实际上总是HTTP通讯。 21 ftp 22 ssh(security shell) 443 https …
3、动态和、私有端口
第三类:动态和/或私有端口(Dynamic and/or Private Ports):从49152到65535。理论上,不应为服务分配这些端口。实际上,机器通常从1024起分配动态端口
2.Tcp与UDP概念
网络七层协议: 网络层,数据链路层,网络层ip,传输层,会话层,表示层,应用层
传输层两个重要协议
TCP(Transmission Control Protocol)连通性
传输控制协议,提供可靠无差错的数据传输,保证数据正确性,速度慢,占用系统资源高,TCP面向连接。每条TCP传输连接只能有两个端点,只能进行点对点的数据传输,不支持多播和广播传输方式。
UDP(User Datagram Protocol)()
用户数据报协议,不可靠的数据传输,可能丢包,速度快,占用资源较少,UDP面向无连接。UDP支持一对一,一对多,多对一和多对多的交互通信。
3.Socket编程原理
服务器端
(1) 创建ServerSocket对象,绑定监听端口;
(2) 通过accept()方法监听客户端请求(产生阻塞);
(3) 连接建立后,通过输入流读取客户端发送的请求信息;
(4) 通过输出流向客户端发送相应信息;
(5) 关闭相应资源。
客户端
(1)创建Socket对象,指明需要连接的服务器地址和端口;
(2)连接建立后,通过输出流向服务器端发送请求信息;
(3)通过输入流获取服务器端返回的响应信息;
(4)关闭相应资源;
4.代码
/** * @author zhangyifan * @version 8.0 * @description:服务器 * @date 2021/12/7 9:56 */ public class Server { public static void main(String[] args) { ServerSocket serverSocket= null; Socket socket=null; BufferedReader bufferedReader=null; PrintWriter printWriter=null; try { // (1) 创建ServerSocket对象,绑定监听端口; serverSocket = new ServerSocket(16666); System.out.println("服务器以准备就绪,等待连接"); // (2) 通过accept()方法监听客户端请求(产生阻塞); socket= serverSocket.accept();//监听 //按行读取提高效率 需要把字节流转换成字符流 bufferedReader=//BufferedReader在字符流套接缓存,提高读写效率 new BufferedReader( //InputStreamReader吧字节流转字符流 new InputStreamReader( socket.getInputStream()) ) ; //按行读取客户端信息 String s = bufferedReader.readLine(); //打印 System.out.println("客户端说"+s); // (4) 通过输出流向客户端发送相应信息; printWriter =new PrintWriter(socket.getOutputStream()); //写入信息 printWriter.println("你好客户端 收到了信息"+s+",给你回复"); //清空管道 printWriter.flush(); } catch (IOException e) { e.printStackTrace(); }finally { if (printWriter!=null){ printWriter.close(); } if (bufferedReader!=null){ try { bufferedReader.close(); } catch (IOException e) { e.printStackTrace(); } } if (socket!=null){ try { socket.close(); } catch (IOException e) { e.printStackTrace(); } } if (serverSocket!=null){ try { serverSocket.close(); } catch (IOException e) { e.printStackTrace(); } } } } } /** * @author zhangyifan * @version 8.0 * @description:客户端 * @date 2021/12/7 10:35 */ public class Client { public static void main(String[] args) { Socket socket= null; PrintWriter printWriter=null; BufferedReader bufferedReader=null; try { // (1) 创建Socket对象,指明需要连接的服务器地址和端口; socket = new Socket("192.168.41.26",16666); // (2) 连接建立后,通过输出流向服务器端发送请求信息; printWriter=new PrintWriter(socket.getOutputStream()); //写入消息 printWriter.println("你好服务器"); //写入消息 printWriter.flush(); // (3) 通过输入流获取服务器端返回的响应信息; bufferedReader= new BufferedReader(new InputStreamReader(socket.getInputStream())); //按行读取信息 String s = bufferedReader.readLine(); //打印 System.out.println("服务器说"+s); } catch (IOException e) { e.printStackTrace(); }finally { //关闭资源 if (bufferedReader!=null){ try { bufferedReader.close(); } catch (IOException e) { e.printStackTrace(); } } if (printWriter!=null){ printWriter.close(); } if (socket!=null){ try { socket.close(); } catch (IOException e) { e.printStackTrace(); } } } } }
持续通话
有问题的代 码 发送消息有时会不及时
/** * @author zhangyifan * @version 8.0 * @description: * @date 2021/12/7 14:19 */ public class Server { public static void main(String[] args) { ServerSocket serverSocket=null; Socket socket=null; BufferedReader bufferedReader=null; PrintWriter printWriter=null; /* (1) 创建ServerSocket对象,绑定监听端口; (2) 通过accept()方法监听客户端请求(产生阻塞); (3) 连接建立后,通过输入流读取客户端发送的请求信息; (4) 通过输出流向客户端发送相应信息; (5) 关闭相应资源。*/ try { // (1) 创建ServerSocket对象,绑定监听端口; serverSocket=new ServerSocket(16666); System.out.println("服务器准备就绪+等待客户端连接"); // (2) 通过accept()方法监听客户端请求(产生阻塞); socket=serverSocket.accept(); // (3) 连接建立后,通过输入流读取客户端发送的请求信息; bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream())); //(4) 通过输出流向客户端发送相应信息; printWriter=new PrintWriter(socket.getOutputStream()); Scanner scanner=new Scanner(System.in); while (true){ //读取客户端· String clientMsg = bufferedReader.readLine(); System.out.println("客户端说"+clientMsg); //包含 if (clientMsg.contains("借钱")){ printWriter.println("你被啦黑了");//写出 printWriter.flush();//刷新 break; } //提示 System.out.println("请输入:"); //阻塞并等待控制台输入 String serverinputMsg = scanner.next(); //写入信息 printWriter.println(serverinputMsg); //刷新 printWriter.flush(); } } catch (IOException e) { e.printStackTrace(); }finally { // (5) 关闭相应资源。 if(printWriter!=null){ printWriter.close(); } try { if(bufferedReader!=null){ bufferedReader.close(); } } catch (IOException e) { e.printStackTrace(); } try { if(socket!=null){ socket.close(); } } catch (IOException e) { e.printStackTrace(); } try { if(serverSocket!=null){ serverSocket.close(); } } catch (IOException e) { e.printStackTrace(); } } } } /** * @author zhangyifan * @version 8.0 * @description: * @date 2021/12/7 14:19 */ public class Client { public static void main(String[] args) { Socket sOcket=null; PrintWriter printWriter=null; BufferedReader bufferedReader=null; // (1)创建Socket对象,指明需要连接的服务器地址和端口; try { sOcket=new Socket("192.168.41.26",16666); //(2)连接建立后,通过输出流向服务器端发送请求信息; printWriter =new PrintWriter(sOcket.getOutputStream()); //(3)通过输入流获取服务器端返回的响应信息; bufferedReader= new BufferedReader(new InputStreamReader(sOcket.getInputStream())); Scanner scanner=new Scanner(System.in); while (true){ System.out.println("请输入:"); String clientInputMsg = scanner.next(); printWriter.println(clientInputMsg); printWriter.flush(); String ServerMSG=bufferedReader.readLine(); System.out.println("服务器说"+ServerMSG); if (ServerMSG.contains("拉黑")){ printWriter.println("别慌,拉黑前借钱"); printWriter.flush();//刷新 break;//退出 } } } catch (IOException e) { e.printStackTrace(); }finally { // (4) 关闭相应资源。 try { if(bufferedReader!=null){ bufferedReader.close(); } } catch (IOException e) { e.printStackTrace(); } if(printWriter!=null){ printWriter.close(); } try { if(sOcket!=null){ sOcket.close(); } } catch (IOException e) { e.printStackTrace(); } } } }
多线程持续通话 可创建多个Client并 但是信息发送必须有去有回否则Server不知道下一个发给谁
/** * @author zhangyifan * @version 8.0 * @description: * @date 2021/12/7 15:11 */ public class Server { public static void main(String[] args) { ServerSocket serverSocket=null; try { serverSocket=new ServerSocket(16666); while (true){ System.out.println("服务端已经准备就绪,等待客户端连接。。。。"); //等待客户端连接 Socket accept = serverSocket.accept(); new Thread(new MTServer(accept)).start(); } } catch (IOException e) { e.printStackTrace(); } } } /** * @author zhangyifan * @version 8.0 * @description: * @date 2021/12/7 15:11 */ public class MTServer implements Runnable{ private Socket socket; //赋值 public MTServer(Socket socket) { this.socket = socket; } @Override public void run() { //提示 System.out.println("客户端"+Thread.currentThread().getName()+"已经连接,可以对话"); BufferedReader bufferedReader=null; PrintWriter printWriter=null; try {//转换 bufferedReader= new BufferedReader(new InputStreamReader(socket.getInputStream())); //发送 printWriter=new PrintWriter(socket.getOutputStream()); Scanner scanner=new Scanner(System.in); while (true){ String clientMsg = bufferedReader.readLine(); //打印 System.out.println("客户端"+clientMsg); //阻塞并等待控制台输入 System.out.println("请求输入"); String serverInputMsg = scanner.next(); //写入信息 printWriter.println(serverInputMsg); //刷新管道 printWriter.flush(); if (clientMsg.contains("借钱")){ printWriter.println("你被拉黑了"); printWriter.flush();//刷新 } } } catch (IOException e) { e.printStackTrace(); }finally { // (5) 关闭相应资源。 if (printWriter != null) { printWriter.close(); } try { if (bufferedReader != null) { bufferedReader.close(); } } catch (IOException e) { e.printStackTrace(); } try { if (socket != null) { socket.close(); } } catch (IOException e) { e.printStackTrace(); } } } } /** * @author zhangyifan * @version 8.0 * @description: * @date 2021/12/7 15:11 */ public class Client { public static void main(String[] args) { Socket socket=null; PrintWriter printWriter=null; BufferedReader bufferedReader=null; try { socket=new Socket("192.168.41.26",16666); printWriter =new PrintWriter(socket.getOutputStream()); bufferedReader=new BufferedReader(new InputStreamReader(socket.getInputStream())); /*printWriter.println(bufferedReader.readLine());*/ Scanner scanner=new Scanner(System.in); while(true){ System.out.println("请输入"); //获取 String next = scanner.next(); //发出 printWriter.println(next); //刷新 printWriter.flush(); //行读取 String s = bufferedReader.readLine(); System.out.println("服务器说"+s); if (s.contains("拉黑")){ printWriter.println("别慌,拉黑前借钱"); printWriter.flush(); break; } } } catch (IOException e) { e.printStackTrace(); }finally { // (4) 关闭相应资源。 try { if(bufferedReader!=null){ bufferedReader.close(); } } catch (IOException e) { e.printStackTrace(); } if(printWriter!=null){ printWriter.close(); } try { if(socket!=null){ socket.close(); } } catch (IOException e) { e.printStackTrace(); } } } }
5.UDP程序的原理
服务器端
- 创建服务端DatagramSocket类
- 准备数据 以字节数组的形式
- 打包 DatagramPacket+客户端的地址和端口
- 发送
- 释放资源
客户端
- 创建客户端 DatagramSocket 类 + 指定的接收端口
- 准备接收数据的容器 以字节数组的形式封装为DatagramPacket
- 包 接收数据
- 分析 (组装字节数组)
- 释放资源
6.主要类的方法
DatagramSocket类 要用于实现信息的发送和接收
public DatagramSocket() | 构造DatagramSocket对象,不指定监听的端口 |
---|---|
public DatagramSocket(int port) | 构造DatagramSocket对象,同时指定监听的端口 |
public void send (DatagramPacket p) | 发送数据报 |
public void receive(DatagramPacket p) | 接收数据报 |
DatagramPacket类用于包装需要发送或接收的信息
ublic DatagramPacket(byte[] buf,int length) | 用来接收长度为length的数据包,length测试必须小于等于buf。length |
---|---|
public DatagramPacket(byte[] buf,int length,InetAddressaddress,int port) | 构造数据报包,用来将长度为 length 的包发送到指定主机上的指定端口号 |
public byte[] getData() | 返回接收数据 |
public intgetLength() | 返回要发送或者接收数据的长度 |
7、代码具体实现
/** * @author zhangyifan * @version 8.0 * @description: * @date 2021/12/7 11:36 */ public class Client { public static void main(String[] args) { DatagramSocket datagramSocket=null; try { //1创建连接 datagramSocket=new DatagramSocket(18888); // 2准备接受容器 设置大小 byte[] tempBytes=new byte[1024]; DatagramPacket datagramPacket=new DatagramPacket(tempBytes,1024); //3、包接受信息 System.out.println("客户端准备就绪,等待服务器"); datagramSocket.receive(datagramPacket); //4 分析 组装字节数组 String s = new String(tempBytes, 0, datagramPacket.getLength()); System.out.println("收到信息"+s); } catch ( Exception e) { e.printStackTrace(); }finally { if (datagramSocket!=null){ datagramSocket.close(); } } } } /** * @author zhangyifan * @version 8.0 * @description: * @date 2021/12/7 11:36 */ public class Server { public static void main(String[] args) { DatagramSocket datagramSocket=null; try { //创建服务端 DatagramSocket类 datagramSocket=new DatagramSocket(); //准备数据 字节 String str="hello client"; byte[] sendMsgBytes=str.getBytes();//装字节 //1、 发送消息的字节数组 2.发送消息字节数组的长度 3.ip 4 端口号 DatagramPacket datagramPacket= new DatagramPacket(sendMsgBytes , sendMsgBytes.length , InetAddress.getByName("localhost") ,18888); //发送 datagramSocket.send(datagramPacket); System.out.println("消息发送完毕"); } catch ( Exception e) { e.printStackTrace(); }finally { //释放资源 if (datagramSocket!=null){ datagramSocket.close(); } } } }
注意事项:先启动客户端,receive方法在接收到数据报前一直阻塞。再运行服务器端。
8、UDP对聊
总结
这篇关于Socket编程的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-23增量更新怎么做?-icode9专业技术文章分享
- 2024-11-23压缩包加密方案有哪些?-icode9专业技术文章分享
- 2024-11-23用shell怎么写一个开机时自动同步远程仓库的代码?-icode9专业技术文章分享
- 2024-11-23webman可以同步自己的仓库吗?-icode9专业技术文章分享
- 2024-11-23在 Webman 中怎么判断是否有某命令进程正在运行?-icode9专业技术文章分享
- 2024-11-23如何重置new Swiper?-icode9专业技术文章分享
- 2024-11-23oss直传有什么好处?-icode9专业技术文章分享
- 2024-11-23如何将oss直传封装成一个组件在其他页面调用时都可以使用?-icode9专业技术文章分享
- 2024-11-23怎么使用laravel 11在代码里获取路由列表?-icode9专业技术文章分享
- 2024-11-22怎么实现ansible playbook 备份代码中命名包含时间戳功能?-icode9专业技术文章分享