如何学习 Java 中的 Socket 编程,进行网络通信

Socket编程是网络编程的核心技术之一,它使得不同主机之间可以进行数据通信。Java提供了丰富的网络编程API,使得编写网络应用程序变得相对简单和直观。本文将详细讲解如何学习Java中的Socket编程,并通过示例代码展示如何实现网络通信。

一、Socket编程基础

1.1 什么是Socket?

Socket是一种网络通信的端点,包含IP地址和端口号。在网络通信中,一个Socket实例代表一个网络连接的一个端点,通过两个Socket实例(客户端和服务器)可以实现网络通信。

1.2 TCP和UDP

Socket编程主要分为两种类型:基于TCP(Transmission Control Protocol)的Socket编程和基于UDP(User Datagram Protocol)的Socket编程。

  • TCP:面向连接的协议,提供可靠的、顺序正确的、无差错的数据传输。常用于需要高可靠性的场景。
  • UDP:无连接的协议,提供不保证可靠性的数据传输。适用于对传输速度要求较高,但对可靠性要求较低的场景。

二、Java中的Socket类

2.1 Java Socket API

Java提供了以下主要的Socket编程类:

  • java.net.Socket:实现客户端Socket,负责与服务器建立连接并进行通信。
  • java.net.ServerSocket:实现服务器Socket,负责监听客户端的连接请求。
  • java.net.DatagramSocket:实现UDP协议的Socket,用于发送和接收数据报文。
  • java.net.DatagramPacket:表示UDP的数据报文。

三、基于TCP的Socket编程

3.1 客户端Socket编程

客户端通过java.net.Socket类实现。步骤如下:

  1. 创建Socket对象,并连接到服务器。
  2. 获取输入输出流,用于发送和接收数据。
  3. 关闭Socket连接。

示例代码:

import java.io.*;
import java.net.*;public class TCPClient {public static void main(String[] args) {String serverName = "localhost"; // 服务器地址int port = 8080; // 服务器端口try {// 连接到服务器Socket client = new Socket(serverName, port);// 获取输出流,发送数据到服务器OutputStream outToServer = client.getOutputStream();DataOutputStream out = new DataOutputStream(outToServer);out.writeUTF("Hello from " + client.getLocalSocketAddress());// 获取输入流,接收服务器返回的数据InputStream inFromServer = client.getInputStream();DataInputStream in = new DataInputStream(inFromServer);System.out.println("Server says " + in.readUTF());// 关闭连接client.close();} catch (IOException e) {e.printStackTrace();}}
}
3.2 服务器Socket编程

服务器通过java.net.ServerSocket类实现。步骤如下:

  1. 创建ServerSocket对象,并绑定到指定端口。
  2. 调用accept()方法,等待客户端连接。
  3. 获取输入输出流,用于接收和发送数据。
  4. 关闭Socket连接。

示例代码:

import java.io.*;
import java.net.*;public class TCPServer {public static void main(String[] args) {int port = 8080; // 监听端口try {// 创建服务器SocketServerSocket serverSocket = new ServerSocket(port);while (true) {// 等待客户端连接Socket server = serverSocket.accept();// 获取输入流,接收客户端发送的数据DataInputStream in = new DataInputStream(server.getInputStream());System.out.println("Client says " + in.readUTF());// 获取输出流,发送数据到客户端DataOutputStream out = new DataOutputStream(server.getOutputStream());out.writeUTF("Thank you for connecting to " + server.getLocalSocketAddress());// 关闭连接server.close();}} catch (IOException e) {e.printStackTrace();}}
}

四、基于UDP的Socket编程

4.1 客户端Socket编程

客户端通过java.net.DatagramSocketjava.net.DatagramPacket类实现。步骤如下:

  1. 创建DatagramSocket对象。
  2. 创建DatagramPacket对象,封装要发送的数据。
  3. 调用send()方法发送数据。
  4. 调用receive()方法接收数据。
  5. 关闭DatagramSocket。

示例代码:

import java.net.*;public class UDPClient {public static void main(String[] args) {String serverName = "localhost"; // 服务器地址int port = 8080; // 服务器端口try {// 创建客户端SocketDatagramSocket clientSocket = new DatagramSocket();// 发送数据byte[] sendData = "Hello from client".getBytes();InetAddress IPAddress = InetAddress.getByName(serverName);DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, IPAddress, port);clientSocket.send(sendPacket);// 接收数据byte[] receiveData = new byte[1024];DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);clientSocket.receive(receivePacket);String modifiedSentence = new String(receivePacket.getData());System.out.println("FROM SERVER: " + modifiedSentence);// 关闭连接clientSocket.close();} catch (Exception e) {e.printStackTrace();}}
}
4.2 服务器Socket编程

服务器通过java.net.DatagramSocketjava.net.DatagramPacket类实现。步骤如下:

  1. 创建DatagramSocket对象,并绑定到指定端口。
  2. 创建DatagramPacket对象,用于接收数据。
  3. 调用receive()方法接收数据。
  4. 创建DatagramPacket对象,封装要发送的数据。
  5. 调用send()方法发送数据。
  6. 关闭DatagramSocket。

示例代码:

import java.net.*;public class UDPServer {public static void main(String[] args) {int port = 8080; // 监听端口try {// 创建服务器SocketDatagramSocket serverSocket = new DatagramSocket(port);while (true) {// 接收数据byte[] receiveData = new byte[1024];DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);serverSocket.receive(receivePacket);String sentence = new String(receivePacket.getData());System.out.println("RECEIVED: " + sentence);// 发送数据InetAddress IPAddress = receivePacket.getAddress();int clientPort = receivePacket.getPort();String capitalizedSentence = sentence.toUpperCase();byte[] sendData = capitalizedSentence.getBytes();DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, IPAddress, clientPort);serverSocket.send(sendPacket);}} catch (Exception e) {e.printStackTrace();}}
}

五、Java Socket编程中的常见问题

5.1 端口冲突

端口冲突是指多个程序尝试绑定到同一个端口,这会导致端口不可用。解决方法是确保每个程序使用不同的端口,或者检查端口是否被占用。

5.2 数据传输中的阻塞

Socket通信是阻塞式的,意味着读写操作会阻塞线程直到数据被完全传输。可以使用多线程或者非阻塞I/O(NIO)来解决这个问题。

5.3 数据粘包与拆包

在TCP协议中,由于数据是以流的形式发送,接收方可能会一次接收到多个数据包(粘包)或一个数据包被分成多次接收(拆包)。解决方法是在数据包中添加长度字段,或者使用定界符来标识每个数据包的边界。

六、高级话题:多线程和NIO

6.1 多线程Socket编程

在实际应用中,服务器通常需要同时处理多个客户端的连接。可以使用多线程来实现,每个客户端连接由一个线程处理。

示例代码:

import java.io.*;
import java.net.*;public class MultiThreadedTCPServer {public static void main(String[] args) {int port = 8080; // 监听端口try {// 创建服务器SocketServerSocket serverSocket = new ServerSocket(port);System.out.println("Server started on port " + port);while (true) {// 等待客户端连接Socket clientSocket = serverSocket.accept();System.out.println("New client connected: " + clientSocket.getInetAddress());// 创建一个新的线程处理客户端请求new ClientHandler(clientSocket).start();}} catch (IOException e) {e.printStackTrace();}}
}class ClientHandler extends Thread {private Socket clientSocket;public ClientHandler(Socket socket) {this.clientSocket = socket;}public void run() {try {// 获取输入流,接收客户端发送的数据DataInputStream in = new DataInputStream(clientSocket.getInputStream());System.out.println("Client says: " + in.readUTF());// 获取输出流,发送数据到客户端DataOutputStream out = new DataOutputStream(clientSocket.getOutputStream());out.writeUTF("Thank you for connecting!");// 关闭连接clientSocket.close();} catch (IOException e) {e.printStackTrace();}}
}
6.2 非阻塞I/O(NIO)

Java NIO(New I/O)提供了非阻塞的网络通信方式,可以提高服务器的性能和扩展性。NIO中的核心组件包括Channel、Buffer和Selector。

示例代码:

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;public class NioTCPServer {public static void main(String[] args) {int port = 8080; // 监听端口try {// 创建选择器Selector selector = Selector.open();// 打开服务器Socket通道ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();serverSocketChannel.socket().bind(new InetSocketAddress(port));serverSocketChannel.configureBlocking(false);serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);System.out.println("Server started on port " + port);while (true) {// 等待事件selector.select();// 获取发生事件的SelectionKeyIterator<SelectionKey> iterator = selector.selectedKeys().iterator();while (iterator.hasNext()) {SelectionKey key = iterator.next();iterator.remove();if (key.isAcceptable()) {// 接受连接ServerSocketChannel serverChannel = (ServerSocketChannel) key.channel();SocketChannel socketChannel = serverChannel.accept();socketChannel.configureBlocking(false);socketChannel.register(selector, SelectionKey.OP_READ);} else if (key.isReadable()) {// 读取数据SocketChannel socketChannel = (SocketChannel) key.channel();ByteBuffer buffer = ByteBuffer.allocate(256);socketChannel.read(buffer);String message = new String(buffer.array()).trim();System.out.println("Client says: " + message);// 响应客户端buffer.flip();socketChannel.write(buffer);}}}} catch (IOException e) {e.printStackTrace();}}
}

黑马程序员免费预约咨询

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/854833.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java情侣飞行棋系统小程序+H5+微信公众号+APP 源码

&#x1f491;甜蜜互动&#xff0c;共赴云端之旅&#x1f6eb; &#x1f308;一、引言&#xff1a;飞行棋遇上情侣&#xff0c;乐趣翻倍 在繁忙的生活中&#xff0c;情侣们总是渴望找到一种简单而有趣的方式来增进彼此的感情。这时&#xff0c;情侣飞行棋小程序应运而生&#…

视频融合共享平台LntonCVS视频监控管理平台技术方案详细介绍

LntonCVS国标视频综合管理平台是一款以视频为核心的智慧物联应用平台。它基于分布式、负载均衡等流媒体技术进行开发&#xff0c;提供广泛兼容、安全可靠、开放共享的视频综合服务。该平台具备多种功能&#xff0c;包括视频直播、录像、回放、检索、云存储、告警上报、语音对讲…

【C#】汽车租赁系统设计与实现

目的&#xff1a; 设计一个简单的汽车租赁系统&#xff0c;包含以下功能&#xff1a; 添加车辆&#xff1a;用户可以添加新的车辆到系统中&#xff0c;包括车辆的品牌、型号、车牌号、日租金等信息。查找车辆&#xff1a;用户可以通过车牌号或者品牌来查找车辆&#xff0c;并…

MyBatis查询两个字段,返回Map,一个字段作为key,一个字段作为value的实现

项目场景&#xff1a; 在使用MyBatis&#xff0c;我们经常会遇到这种情况&#xff1a;SELECT两个字段&#xff0c;需要返回一个Map&#xff0c;其中第一个字段作为key&#xff0c;第二个字段作为value。MyBatis的MapKey虽然很实用&#xff0c;但并不能解决这种场景。 问题描述 …

【Unity】向量应用:已知入射方向和法向量求反射方向(跳弹系统)

文章目录 已知入射方向和法向量求反射方向已知条件解题思路代码范例 已知入射方向和法向量求反射方向 已知条件 已知入射向量v1和法向量n&#xff08;OB&#xff09;&#xff0c;求反射向量v2&#xff0c;上述向量均为单位向量。 解题思路 设 AO为 v1 &#xff1b;OB为 n …

实验13 BGP路径选择

实验13 BGP路径选择 一、 原理描述二、 实验目的三、 实验内容四、 实验配置五、 实验步骤 一、 原理描述 与域内路由不同&#xff0c;域间路由更加注重策略&#xff0c;而不是技术。在域内进行选路&#xff0c;可以使用路由算法计算出到达目的子网的最短路径&#xff1b;而在…

如何完美解决 Oracle Database 19c 安装程序 - 第7步(共8步)卡住,半小时都不动

&#x1f680; 如何完美解决 Oracle Database 19c 安装程序 - 第7步&#xff08;共8步&#xff09;卡住&#xff0c;半小时都不动 摘要 在安装 Oracle Database 19c 时&#xff0c;很多用户会在第7步&#xff08;共8步&#xff09;遇到卡住的问题&#xff0c;尤其是安装程序长…

行业模板|DataEase应用平台对接大屏模板推荐

DataEase开源数据可视化分析工具于2022年6月发布模板市场&#xff08;https://templates-de.fit2cloud.com&#xff09;&#xff0c;并于2024年1月新增适用于DataEase v2版本的模板分类。模板市场旨在为DataEase用户提供专业、美观、拿来即用的大屏模板&#xff0c;方便用户根据…

Spring框架的最新进展:2023年Spring Boot和Spring Cloud功能更新

引用 Spring框架的最新动态&#xff1a;2023年Spring Boot与Spring Cloud功能升级 Spring框架作为Java开发领域的重要技术之一&#xff0c;一直致力于简化开发流程和提高开发效率。2023年&#xff0c;Spring Boot和Spring Cloud两大核心组件再次迎来功能升级&#xff0c;为开…

哪个充电宝牌子好用又实惠?盘点四大平价充电宝分享

在当今快节奏的生活中&#xff0c;充电宝已成为我们日常生活中不可或缺的一部分。然而&#xff0c;面对市场上琳琅满目的充电宝品牌和型号&#xff0c;许多消费者误以为选择容量越大、价格越高的充电宝就是最好的选择。实际上&#xff0c;买充电宝并不是一味追求高容量和高价格…

深入解析知识付费平台的核心功能模块:满足个性化学习需求的数字化教育新星

在数字化学习的大潮中&#xff0c;知识付费平台已成为教育行业的一颗新星&#xff0c;它以满足用户需求为核心&#xff0c;提供便捷高效的学习渠道。该平台汇聚了各类专业知识&#xff0c;覆盖职业技能、生活兴趣和人文社科等多个领域&#xff0c;满足不同用户的学习需求。同时…

【scrapy】爬虫,从429状态码说起

许久未爬&#xff0c;发现爬不动了&#xff0c;哈哈哈&#xff0c;记录下这次失败的爬取经历 问题描述 针对这样的一个网站&#xff1a; https://www.farfetch.cn/cn/shopping/women/dresses-1/items.aspx?page1&view96&sort3 需求&#xff1a; 1.需要爬取列表页…

TOP10!YashanDB斩获广东省优秀信创产品与解决方案双料荣誉

近日&#xff0c;2024广东软件风云榜结果出炉&#xff0c;表彰为广东软件产业和数字经济、新型工业化发展作出突出贡献的企业、企业家、优秀产品等。深算院崖山数据库系统 YashanDB荣获广东省“2024年优秀信息技术应用创新产品TOP10”和“2024年优秀信息技术应用创新行业应用解…

java 对象实际占用内存大小预估工具类ObjectSizeUtil

java 对象实际占用内存大小预估工具类 返回对象占用预估字节数 返回字节数对应格式化后的字符串&#xff08;xx Kb&#xff09; 使用效果 依赖了lombock和hutool&#xff0c;项目不用这个可以去掉日志&#xff0c;稍微改写一下。 import cn.hutool.core.util.ClassUtil; i…

docker怎么拉取全部镜像,打包所有镜像

因为docker&#xff0c;所以我把电脑上之前的镜像全部打包出来了 你们也可以打包&#xff0c;我提供一个脚本&#xff0c;你运行即可 export_docker.sh #!/bin/bash# 导出目录 EXPORT_DIR"docker_images_backup" mkdir -p "$EXPORT_DIR"# 获取所有镜像 …

PythonPoc基础编写(3)---批量刷cnvd

文章目录 前言一、发现过程二、使用步骤1.引入库2.读入数据结果 总结 前言 想刷cnvd&#xff1f;最重要的是登录进行测试功能点 一、发现过程 找到一个网站 发现登录失败返回200 登录成功则是重定向 302 那就写一个脚本吧 二、使用步骤 1.引入库 import requests 2.读入…

安装AutoCAD异常

问题&#xff1a; 安装Autodesk产品时&#xff0c;显示以下消息&#xff0c;且安装未完成。 正在等待操作系统重新启动。 请重新启动计算机以安装 AutoCAD 2024。 操作系统&#xff1a; Windows 10Windows 11 原因&#xff1a; Windows注册表项已损坏。Microsoft Visual C …

微射流均质机可用于纳米制剂和材料制备 我国市场需求空间广阔

微射流均质机可用于纳米制剂和材料制备 我国市场需求空间广阔 微射流均质机是一种纳米级乳化及分散的处理设备&#xff0c;工作原理是在加压状态下&#xff0c;高压流体经过微细孔径喷嘴后&#xff0c;形成高速微射流&#xff0c;从而产生强大的涡流和切应力&#xff0c;将颗粒…

ESP8266-01S烧录MQTT固件ERROR问题

今天在烧录ESP8266固件时遇到了这个问题&#xff0c;技术客服给了个有效的解决方案。 选择固件的时候可以先确认自己的模块是ESP8266或者EPS8285主控&#xff0c;这在选择DOWNLOADTOOL时还不一样。 然后波特率是115200&#xff0c;我在这个地方选错成1152000。 当然上面都不…

【ARM Cache 及 MMU 系列文章 1.4 -- 如何判断 L3 Cache 是否实现?】

请阅读【ARM Cache 及 MMU/MPU 系列文章专栏导读】 及【嵌入式开发学习必备专栏】 文章目录 Cluster Configuration Register代码实现什么是Single-Threaded Core?什么是PE(Processor Execution units)?Single-Threaded Core与PE的关系对比多线程(Multithreading)Cluster…