深入理解Java Socket通信
作者:郑州的文武 发布时间:2022-10-03 04:56:10
简述
Java中Socket分为普通Socket和NioSocket两种,这里介绍Socket。
我们可以把Socket比作两个城市间的交通工具,有了它可以在两城之间来回穿梭,交通工具有很多种,每种交通工具也有相应的交通规则。Socket也一样,也有多种。大多情况下使用的是TCP/IP的流套接字,它是一种稳定的通信协议。(TCP/IP与UDP的对比)
Java中的网络通信是通过Socket实现的,Socket分为ServerSocket和Socket两大类,ServerSocket用于服务端,通过accept方法监听请求,监听到请求后返回Socket,Socket用于具体完成数据传输,客户端直接使用Socket发起请求并传输数据。
ServerSocket的使用可以分为三步:
1.创建ServerSocket。ServerSocket的构造方法一共有5个,通常用的是ServerSocket(int port),只需要端口号(port)即可。
2.调用创建出来的ServerSocket的accept方法进行监听。accept方法时阻塞方法,也就是说调用accept方法后程序会停下来等待连接请求,在接收到请求之前程序将不会往下走。当接收到请求后accept方法会返回一个Socket。
3.使用accept方法返回的Socket与客户端进行通信。
栗子
Client:
package IO;
import java.io.*;
import java.net.Socket;
import java.util.Date;
/**
* Created by zhengbin06 on 2017/2/2.
*/
public class Client {
public static void main(String[] args) {
String msg = "Client Data";
try {
Socket socket = new Socket("127.0.0.1", 9090);
// 先写、再读
PrintWriter printWriter = new PrintWriter(socket.getOutputStream());
// 发送数据
printWriter.println(msg);
printWriter.flush();
// 获得服务端返回的数据
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line = bufferedReader.readLine();
System.out.println("received from server: " + line + "\ttime=" + new Date().getTime());
// 关闭资源
printWriter.close();
bufferedReader.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Server:
package IO;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Date;
/**
* Created by zhengbin06 on 2017/2/2.
*/
public class Server {
private static Socket socket = null;
private static ServerSocket serverSocket = null;
public static void main(String[] args) throws IOException {
BufferedReader bufferedReader = null;
PrintWriter printWriter = null;
try {
// 创建一个ServerSocket监听9090端口
serverSocket = new ServerSocket(9090);
while (true) {
System.out.println("开始等待请求。。。。");
// 等待请求
// 监听并接受到此套接字的连接。此方法在连接传入之前一直阻塞。
socket = serverSocket.accept();
System.out.println("接收到请求:" + socket.toString() + "\ttime=" + new Date().getTime());
// 接收到请求后使用socket进行通信, 创建BufferedReader用于读取数据
bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line = bufferedReader.readLine();
System.out.println("received from client: " + line + "\ttime=" + new Date().getTime());
// 创建PrintWriter, 用于发送数据
printWriter = new PrintWriter(socket.getOutputStream());
printWriter.println("received data: " + line + "\ttime=" + new Date().getTime());
printWriter.flush();
}
} finally {
// 关闭所有资源
bufferedReader.close();
printWriter.close();
socket.close();
serverSocket.close();
}
}
}
细节
监听请求:
当一个新的Socket请求来到时,将为这个连接创建一个新的套接字数据结构,该套接字数据的信息包含的地址和端口正式请求源地址和端口。这个新创建的数据结构将会关联到ServerSocket实例的一个未完成的连接数据结构列表中。注意,这时服务端的与之对应的Socket实例并没有完成创建,而要等到与客户端的3次握手完成后,这个服务端的Socket实例才会返回,并将这个Socket实例对应的数据结构从未完成列表中移动已完成列表中。
数据传输:
当连接已经建立成功时,服务端和客户端都会拥有一个Socket实例,每个Socket实例都有一个InputStream和OutputStream,并通过这两个对象来交换数据。
要知道网络I/O都是以字节流传输的,当创建Socket对象时,操作系统将会为InputStream和OutputStream分别分配一定大小的缓存区,数据的写入和读取都是通过这个缓存区完成的。
写入端将数据写到OutputStream对应的SendQ队列中,当队列填满时,数据将被转移到另一端InputStream的RecvQ队列中,如果这时RecvQ已经满了,那么OutputStream的write方法将会阻塞,直到RecvQ队列有足够的空间容纳SendQ发送的数据。过程如下图所示:
来源:http://www.cnblogs.com/zhengbin/p/6367918.html
猜你喜欢
- 在使用SpringBoot做接口访问如何做接口的限流,这里我们可以使用google的Guava包来实现,当然我们也可以自己实现限流,Guav
- 对于一个应用程序而言,控件是搭建用户界面的积木。它们具备交互式的特征。VS 2012中的控件都放在工具箱中,添加一个控件到窗体,只需在工具箱
- 本文实例讲述了C#实现DataTable映射成Model的方法。分享给大家供大家参考,具体如下:这是数据库开发中经常遇到的问题,当然,这可以
- 在分支较多的时候,switch的效率比if高,在反汇编中我们即可看到效率高的原因一、switch语句1、在正向编码时,switch语句可以看
- Spring中Profile对不同环境提供不同配置功能的支持,可以通过激活、指定参数等方式快速切换环境。文件名格式:application-
- 内部类1. 内部类简介(1) 内部类提供了更好的封装,可以把内部类隐藏在外部类之内,不允许同一个包中的其他类访问该类。(2) 内部类成员可以
- 前段时间,有个同事说“30000000000000000000000000000000000000000000000000000000000
- 一、Java 运行时数据区域友情提示:这部分内容可能大部分同学都有一定的了解了,可以跳过直接进入下一小节哈。Java 虚拟机在执行 Java
- JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式,易于阅读和编写,同时也易于机器解析和生成。同X
- 数据库表结构departmentemployee要求一现在的要求是输入 id 把 employee 表的对应员工数据查询出来,并且查询出该员
- 概述动态SQL:SQL语句会随着用户输入或外部条件的变化而变化 。例如:我们在做多条件查询的时候,编写SQL语句的查询操作,我们并不知道用户
- 前言在手写sql的时候,根据参数处理查询条件.select * from staff where 1 = 1 and staff_id in
- 如下所示:class Program {
- 昨天有个刚学java的师弟发了个程序给我,说死活编译不过,老是报编码问题,自己试了一下,也出问题了...当我们编辑了一个Java源文件保存时
- 一、技术介绍线上演示地址:http://chat.breez.work实时通信(Instant Messaging,简称IM)是一个实时通信
- 1、这个方法在GpsNET.JT809Core里来源:https://www.cnblogs.com/cnsend/p/12197982.h
- 1,在项目上鼠标右键 --> Open Module Settings2, Artifacts --> + --> JAR
- 又忙了一周,事情差不多解决了,终于有可以继续写我的博客了(各位看官久等了)。这次我们来谈一谈Java里的一个很有意思的东西——回调。什么叫回
- 1.强引用( Strong Reference )最普遍的引用:Object obj=new Object()抛出OutOfMemoryEr
- java中next与nextLine用法区别:next()一定要读取到有效字符后才可以结束输入,对输入有效字符之前遇到的空格键、Tab键或E