java TCP Socket 数据传输,服务端与客户端
1. socket通信基本原理
socket 通信是基于TCP/IP 网络层上的一种传送方式,我们通常把TCP和UDP称为传输层。
如上图,在七个层级关系中,我们讲的socket属于传输层,其中UDP是一种面向无连接的传输层协议。UDP不关心对端是否真正收到了传送过去的数据。如果需要检查对端是否收到分组数据包,或者对端是否连接到网络,则需要在应用程序中实现。UDP常用在分组数据较少或多播、广播通信以及视频通信等多媒体领域。在这里我们不进行详细讨论,这里主要讲解的是基于TCP/IP协议下的socket通信。socket是基于应用服务与TCP/IP通信之间的一个抽象,他将TCP/IP协议里面复杂的通信逻辑进行分装,对用户来说,只要通过一组简单的API就可以实现网络的连接 | 如上图,服务端初始化ServerSocket,然后对指定的端口进行绑定,接着对端口及进行监听,通过调用accept方法阻塞,此时,如果客户端有一个socket连接到服务端,那么服务端通过监听和accept方法可以与客户端进行连接 |
2. socket通信基本示例:
- 服务端
package com.example.demo1.util;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class TcpServer {
public static void main(String[] args) {
//创建服务器端的Socket对象
ServerSocket serverSocket = null;
InputStream inputStream = null;
OutputStream outputStream = null;
try {
// 创建socket的端口号
serverSocket = new ServerSocket(2000);
// 持续保持启动状态,使客户端能连接,使socket能够一直创建
while (!serverSocket.isClosed()) {
//监听客户端连接,返回一个Socket对象
Socket socket = serverSocket.accept();
//获取输入流,读数据,并把数据显示在控制台
inputStream = socket.getInputStream();
byte[] bys = new byte[1024];
int len = inputStream.read(bys);
//String通过解码指定的字节数组使用平台的默认字符集
String str = new String(bys, 0, len);
//将字符串转成16进制
System.out.println("客户端发送的数据:"+str);
String hexStr = "数据接受成功:"+str;
System.out.println("服务器返回数据:" + hexStr);
outputStream = socket.getOutputStream();
outputStream.write(hexStr.getBytes());
outputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
//释放资源
try {
if (inputStream != null) {
inputStream.close();
}
if (outputStream != null) {
outputStream.close();
}
if (serverSocket != null) {
serverSocket.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
- 客户端
package com.mes.socket;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import java.io.*;
import java.net.Socket;
/**
* @desc socket 通信
* @date 2023/3/3
*/
@Slf4j
public class SocketUtils {
public static void main(String[] args){
Socket socket = null;
OutputStream outputStream = null;
InputStream inputStream = null;
BufferedWriter bufferedWriter = null;
StringBuffer result = new StringBuffer();
try {
// socket 连接 ip ,端口
socket = new Socket("127.0.0.1", 2000);
log.info("-------------------创建socket连接成功-------------------");
inputStream = socket.getInputStream();
outputStream = socket.getOutputStream();
bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream));
// 需要给服务端发送的内容
bufferedWriter.write("你好,这是我的第一个socket");
bufferedWriter.flush();
// 接受返回内容
String msg ="";
while (true) {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
// 返回结果为空跳出while循环
msg = bufferedReader.readLine();
if(StringUtils.isEmpty(msg)){
bufferedReader.close();
break;
}
result.append(msg);
}
log.info("接收到服务端响应:" + result);
}catch (IOException e){
e.printStackTrace();
}finally {
log.info("------------资源释放------------");
try {
if (socket != null) {
socket.close();
}
if (outputStream != null) {
outputStream.close();
}
if (inputStream != null) {
inputStream.close();
}
if (bufferedWriter != null) {
bufferedWriter.close();
}
}catch (IOException e) {
e.printStackTrace();
}
}
log.info("-------------------创建socket连接断开-------------------结果{}",result);
}
}
- 服务端控制台
启动循序,①服务端 ②客户端
详细解释