当前位置: 首页 > 编程日记 > 正文

Socket/ServerSocket 选项

Socket/ServerSocket 选项
原文:Socket/ServerSocket 选项

在网络编程中,Socket/ServerSocket有一些选项用来自定义一些行为,现在分享一下。

Socket选项

1.TCP_NODELAY

在Socket发送数据时,默认情况下,数据会先进入缓冲区,等缓冲区满了再发送出去,意图是为了通过减少传输数据的次数,以此来提高通信效率

但是,对于一些需要即时发送,即时响应的场景并不合适,比如网络游戏。客户端因为采用的默认行为,会等到缓冲区满了后才发送数据,服务端的响应相应也会变慢,导致整个游戏运行起来不流畅。

这时,就要开启TCP_NODELAY,关闭默认行为,实时发送实时响应。

2.SO_TIMEOUT

在读取数据时,常常因为种种原因,导致读方法阻塞,为了保证阻塞时间可控,可以设置SO_TIMEOUT选项,设置读数据时的最大等待时间,如果阻塞时间超过设置的时间,

则会抛出【Exception in thread "main" java.net.SocketTimeoutException: Read timed out】。示例如下。

客户端代码:阻塞6000ms后才发送数据

public class Main {public static void main(String[] args) throws InterruptedException, IOException {Socket socket = new Socket("127.0.0.1", 8899);System.out.println("客户端启动...");OutputStream out = socket.getOutputStream();Thread.sleep(6000); //阻塞6000ms后才发送数据out.write("This is for everyone".getBytes());}
}

服务端代码:通过SO_TIMEOUT选项,设置读阻塞时长最大为5000ms,由于客户端再6000ms后才会出数据,所以会抛出SocketTimeoutException异常。

public class SimpleServer {public static void main(String[] args) throws IOException, InterruptedException {ServerSocket serverSocket = new ServerSocket(8899, 2);System.out.println("服务端启动...");while (true) {Socket socket = serverSocket.accept();System.out.println("连接成功:" + socket);soTimeout(socket);}}private static void soTimeout(Socket socket) throws IOException {socket.setSoTimeout(5000); //设置最大阻塞时间为5000msInputStream in = socket.getInputStream();byte[] buf = new byte[1024];int len = 0;while ((len = in.read(buf)) >= 0) { //因为阻塞时间超过5000ms,所以这里抛出【Exception in thread "main" java.net.SocketTimeoutException: Read timed out】异常System.out.println("read,len=" + len + ",str=" + new String(buf, 0, len));}}
}

3.SO_REUSEADDR

对于Socket来说,当通过Socket.close()关闭时,底层的Socket为了把数据发送完或者接受完,不会立即关闭而是会等待一段时间,确保完成自己的使命。

但这会带来一个问题,由于Socket的端口号不能共享,一旦一个端口号被占用,之后再用这个端口号尝试建立新连接的话会报端口冲突的异常。

为了确保一个进程关闭Socket后,同一主机的其他进程还能使用这个端口,可以设置SO_REUSEADDR选项。

4.SO_LINGER

SO_LINGER选项用来控制Socket关闭时的行为,上面已经简单讲过,默认情况下,调用Socket.close()方法后,close()方法会立即返回,但是底层的Socket会等待数据发送完成后再关闭。

当设置Socket.setSoLinger(true, 0)选项时,close()方法也会立即返回,底层的Socket也会立即关闭,未发送完的数据会抛弃掉。

当设置Socket.setSoLinger(true, n)选项时,close()方法会阻塞,直到满足下列条件中的一个才会返回。

1. n秒后,即使底层Socket还未发送完,也强制关闭底层Socket,并返回close()方法。

2. 底层Socket数据全部发送完(全部送到缓冲区)。

示例如下。

服务端代码:没什么特别的,就是从Socket中读出数据,重点在客户端

public class SimpleServer {public static void main(String[] args) throws IOException, InterruptedException {ServerSocket serverSocket = new ServerSocket(8899, 2);System.out.println("服务端启动...");while (true) {Socket socket = serverSocket.accept();System.out.println("连接成功:" + socket);soLinger(socket);}}// 没什么特别的,就是从Socket中读出数据,重点在客户端private static void soLinger(Socket socket) throws InterruptedException, IOException {InputStream in = socket.getInputStream();byte[] buf = new byte[1024];int len = 0;while ((len = in.read(buf)) >= 0) {System.out.println("read,len=" + len + ",str=" + new String(buf, 0, len));}}
}

客户端代码:首先是不设置SO_LINGER选项,已默认的方式运行。之后#1,close()方法立即返回。#2,close()方法阻塞了4ms。

public class Main {public static void main(String[] args) throws InterruptedException, IOException {Socket socket = new Socket("127.0.0.1", 8899);//socket.setSoLinger(true, 0); #1//socket.setSoLinger(true, 10); #2System.out.println("客户端启动...");OutputStream out = socket.getOutputStream();StringBuilder sb = new StringBuilder();for (int i = 0; i < 500000; i++) {sb.append(i);}out.write(sb.toString().getBytes());long start = System.currentTimeMillis();socket.close();long end = System.currentTimeMillis();System.out.println("close:" + (end - start)); //#1:0   #2:4
    }
}

默认情况下,close()方法立即返回,Socket底层在发送完数据后关闭,服务端正常运行。

当把#1的注释给删掉,close()方法立即返回,Socket底层也会立即关闭,因为客户端数据没有完全发出,所以服务端运行时抛出了【Exception in thread "main" java.net.SocketException: Connection reset】异常

当吧#2的注释给删掉,close()方法阻塞了4ms才返回,Socket底层在发送完数据后关闭,服务端正常运行。

5.SO_RCVBUF,SO_SNDBUF

设置输入,输出缓冲区的大小。

一般情况下,对于数据量大,传输频率低的场景,适合大的缓冲区,减少传输数据的次数,提高传输效率,比如FTP、HTTP等。

对于数据量小,传输频率高,对实时性要求高的场景,适合设置小的缓冲区。

6.SO_KEEPALIVE

检测TCP连接的有效性。大概机制是,2小时后双方没有过交互一直处于空闲状态,则会发送一个请求,如果请求没有响应,则会认为对方已经关闭,这样本地的Socket也会自动关闭。

ServerSocket选项

1.SO_TIMEOUT

ServerSocket.accept()方法是个阻塞方法,会一直阻塞到有一个TCP连接成功建立,SO_TIMEOUT选项则可以设置最大的阻塞时间,超过这个时间还没有建立TCP连接的话则抛出异常。

注意和Socket的SO_TIMEOUT选项区别开,Socket的SO_TIMEOUT选项是设置读操作的最大阻塞时间,ServerSocket的SO_TIMEOUT选项是设置accep()操作的最大阻塞时间。

服务端代码:5000ms后任然没有与某个客户端成功建立连接,所以会抛出SocketTimeoutException异常。

public class SimpleServer {public static void main(String[] args) throws IOException, InterruptedException {ServerSocket serverSocket = new ServerSocket(8899, 2);serverSocket.setSoTimeout(5000); System.out.println("服务端启动...");while (true) {Socket socket = serverSocket.accept(); SO_TIMEOUT选项为5000ms,超过这段时间后,抛出【Exception in thread "main" java.net.SocketTimeoutException: Accept timed out】System.out.println("连接成功:" + socket);}}
}

2.SO_REUSEADDR

同Socket的SO_REUSEADDR选项类似,为了保证一个进程关闭ServerSocket后,即使它还没有释放端口,同一主机的其他进程还能使用这个端口,可以设置SO_REUSEADDR解决这个问题。

对于Socket来讲,一般Socket的端口号都是系统随机分配的,碰巧碰到同一端口的情况比较少。但是对于ServerSocket来讲,往往用的都是固定端口号,所以同一端口的情况就不能忽视了。

3.SO_RCVBUF

设置ServerSocket输入缓冲区的大小。

引用

1.《Java网络编程精解》(孙卫琴)

posted on 2019-03-11 09:26 NET未来之路 阅读(...) 评论(...) 编辑 收藏

转载于:https://www.cnblogs.com/lonelyxmas/p/10508664.html

相关文章:

MySQL主从复制的常用拓扑结构

1、复制的常用拓扑结构 复制的体系结构有以下一些基本原则&#xff1a; (1) 每个slave只能有一个master&#xff1b; (2) 每个slave只能有一个唯一的服务器ID&#xff1b; (3) 每个master可以有很多slave&#xff1b; (4) 如果你设置log_slave_updates&#xff0c;…

统计java文件中的代码行数

统计Java代码行数工具类 —— CodeCounterUtil.java 统计指定目录下的java文件中代码行数 —— public static int getCodeNumFromFolder(String filePath)统计具体文件中的java代码行数 —— public static int getCodeNumFromFile(String filePath)import java.io.Buf…

jQuery插件thickbox在ie下垂直居中问题

jQuery 插件 thickbox 3.1 在ie下总不能垂直居中&#xff0c;按“http://jamazon.co.uk/web/2008/03/17/thickbox-31-ie7-positioning-bug/”上的方法改了也没用&#xff0c;咋办&#xff1f; 我是这样改的&#xff1a;管它ie6还是ie789&#xff0c;一视同仁&#xff01; 原284…

dos分区:C语言建立多个PRI DOS分区

dos分区:C语言建立多个PRI DOS分区 来源: 发布时间:星期四, 2008年9月25日 浏览:127次 评论:0一、引言 在DOS系统下&#xff0c;在计算机应用培训中因培训要求不同&#xff0c; 对软件的要求也不同&#xff0c;由于学员的误操作&#xff0c;存放在硬盘上的软件和重要数据容 易被…

简单几步让CentOS系统时间同步

在使用CentOS系统的时候&#xff0c;我们可能会遇到时间不准的问题&#xff0c;那我们如何解决这个我问题呢&#xff0c;下面就来教大家一个CentOS系统时间同步的方法&#xff0c;希望大家可以解决自己所存在的疑问。 CentOS系统时间同步的步骤如下&#xff1a; 新装的CentOS系…

挨踢人生路--记我的10年18家工作经历 - 后记

挨踢人生路--记我的10年18家工作经历 &#xff0d; 前言挨踢人生路--记我的10年18家工作经历 &#xff0d; 从大学说起――不得不说的一些事情挨踢人生路--记我的10年18家工作经历 &#xff0d; 第1家公司&#xff0c;在老家的工作挨踢人生路--记我的10年18家工作经历 &#xf…

FileUtil

文件工具类 —— FileUtil.java 获取Web工程的根目录 —— String getBasePath()方法获取文件名称 —— public static String getFileName(String filePath)方法获取文件名称前缀 —— public static String getPrefixOfFileName(String filePath)方法获取文件名后缀(…

C# Sato CL4NX打印机发送SBPL指令打印表面信息、RFID芯片数据写入

待更新..转载于:https://www.cnblogs.com/zh7791/p/7650073.html

同步SQL Server 2000 数据库

为什么要同步SQL Server 2000 数据库&#xff0c;它都用在什么场合 数据实时备份同步&#xff0c;数据库服务器出问题时我们也有其正常工作时的备份 数据实时备份同步&#xff0c;一台服务器负载不起时&#xff0c;可以用来做负载均衡 数据实时备份同步&#xff0c;数据库服务器…

【Leecode】两数相加

学习了链表结构&#xff0c;链表中元素的访问&#xff0c;对象指针的初始化与赋值&#xff0c;链表的创建&#xff08;多个节点链接起来&#xff09;&#xff0c;进位计算的表达。 100ms /*** Definition for singly-linked list.* struct ListNode {* int val;* ListN…

推荐一个HTML的语法高亮解析器

http://code.google.com/p/syntaxhighlighter/wiki/Languages支持高亮的语法如下Language Aliases C cpp, c, c C# c#, c-sharp, csharp CSS css Delphi delphi, pascal Java java Java Script js, jscript, javascript PHP php Python py, python Ruby rb, ruby, rails, ror S…

angularJS中directive与controller之间的通信

当我们在angularJS中自定义了directive之后需要和controller进行通讯的时候&#xff0c;是怎么样进行通讯呢&#xff1f; 这里介绍3种angular自定义directive与controller通信的指令。 1.指令作用域中的"" 作用&#xff1a;把当前属性作为字符串传递实现指令与html页…

Eclipse启动失败:No java virtual machine was found after searching the follwing locations

Eclipse启动失败&#xff0c;错误信息如下如所示&#xff1a; 通过阅读错误信息&#xff0c;可以看到错误原因和 javaw.exe路径 有关&#xff1b; 打开eclipse.ini文件&#xff0c;也就是启动Eclipse的初始化文件&#xff1a; 在本地计算机中找到jdk安装路径下javaw.exe文件&a…

Cisco路由器安全配置必用10条命令

当谈到配置一台新的cisco路由器&#xff0c;多数配置依赖于路由器的类型以及它将服务的用途。然而&#xff0c;每位管理员都有其自己的“正确”配置每台路由器的命令列表。笔者将和你分享他自己配置路由器的十条命令列表。<?xml:namespace prefix o ns "urn:schemas…

Tensorflow学习教程------模型参数和网络结构保存且载入,输入一张手写数字图片判断是几...

首先是模型参数和网络结构的保存 #coding:utf-8 import tensorflow as tf from tensorflow.examples.tutorials.mnist import input_datamnist input_data.read_data_sets(MNIST_data,one_hotTrue) #每个批次的大小 batch_size 100 n_batch mnist.train._num_examples // ba…

IntelliJ IDEA乱码问题解决方法

目录 1、设置文件编码 2、设置控制台编码 3、设置Tomcat Server编码 4、修改配置文件编码内容 1、设置文件编码 第1步&#xff1a;打开IDEA&#xff0c;依次点击File、Settings... 打开Setting窗口&#xff1b; 第2步&#xff1a;在Settings窗口中&#xff0c;依次点击Ed…

Windows 7的CMD中 Telnet 无法执行的解决办法

在Windows 7的CMD中&#xff0c;执行telnet 192.168.1.10 80 会提示没有这个命令的提示&#xff0c;这是因为Win7默认是没有安装Telnet的&#xff08;在以往的WINDOWS系统中都是默认安装的&#xff09;。解决办法&#xff1a;在Win7中&#xff0c;进入控制面板&#xff0c;然后…

Qt——模态、非模态

模态&#xff1a; 只能操作对话框非模态&#xff1a;要使用 QDialog *_d new QDialog();_d->setattribute(Qt::WA_DeleteOnClose);_d->show();转载于:https://www.cnblogs.com/yangxinrui/p/10515249.html

c# 取两个时间的间隔

c#可以取两个时间的年月日时分秒之间的间隔&#xff0c;不受跨年月的影响。声明一个 TimeSpan System.TimeSpan ts dtNightEnd.Subtract(dtAmStart); dtNightEnd是原始时间 减去 dtAmStart 这个时间 获得一个TimeSpan TimeSpan 自带了间隔属性 ts.Days.ToString(); ts.Hours.…

MySQL数据表命令

显示表的相关信息&#xff1a; show table status like "表名"&#xff1b; show table status like "表名" \G 格式化&#xff0c;以记录条目形式显示&#xff0c;更清晰 注意&#xff1a;\G后面不能加分号&#xff0c;不然会出现查询错误。因为\G在…

undefined reference to 'pthread_create'问题解决(转)

undefined reference to pthread_createundefined reference to pthread_join问题原因&#xff1a;pthread 库不是 Linux 系统默认的库&#xff0c;连接时需要使用静态库 libpthread.a&#xff0c;所以在使用pthread_create()创建线程&#xff0c;以及调用 pthread_atfork()函数…

C语言程序设计第一次作业

&#xff08;一&#xff09;实验总结 1.圆的面积和周长问题 &#xff08;1&#xff09;题目&#xff1a; 输入圆的半径&#xff0c;计算圆的周长和面积。 &#xff08;2&#xff09;流程图 &#xff08;3&#xff09;测试数据及运行结果 &#xff08;4&#xff09;实验分析 问题…

U盘中毒,无法删除System Volume Information文件夹

情景&#xff1a;U盘中毒&#xff0c;U盘内的文件夹名称变成.exe后缀&#xff0c;且多出一个名为System Volume Information的文件夹&#xff0c;对U盘进行格式化后&#xff0c;所有文件消失&#xff0c;当拔出U盘&#xff0c;再次插入电脑时&#xff0c;发现System Volume Inf…

用Javascript修正12个常见的浏览器问题

我们提倡尽可能使用CSS&#xff0c;而且我们常常能做到这一点。现代浏览器有很好的CSS支持-这无疑足够好让你使用CSS来控制布局和版面设计。但是有时候&#xff0c;某些网页元素在不同的浏览器会出现不同。 如果你不知道原因&#xff0c;不要过于担心&#xff0c;请研究CSS规则…

读书笔记之知识杂点

1.xx1,x1,x,哪个效率最高?为什么? xx1最低&#xff0c;因为它的执行过程如下&#xff1a; &#xff08;1&#xff09;读取右x的地址 &#xff08;2&#xff09;x1 &#xff08;3&#xff09;读取左x的地址 &#xff08;4&#xff09;将右值传给左边的x(编译器并不认为左右的x…

Codeforces.487C.Prefix Product Sequence(构造)

题目链接 \(Description\) 对于一个序列\(a_i\)&#xff0c;定义其前缀积序列为\(a_1\ \mathbb{mod}\ n,\ (a_1a_2)\ \mathbb{mod}\ n,...,(a_1a_2...a_n)\ \mathbb{mod}\ n\)。 给定\(n\)&#xff0c;求一个\(n\)的排列&#xff0c;使得该排列的前缀积序列是\([0,1,2,...,n-1]…

读取CSV文件内容,将其转换成JSON字符串输出

CsvToJsonUtil 工具类作用&#xff1a;读取CSV文件内容&#xff0c;将其转换成JSON字符串输出 转换工具类代码如下&#xff1a; package com.test.util;import java.io.*; import java.io.IOException;public class CsvToJsonUtil {/*** 根据文件路径读取CSV文件 返回String字…

component-scan和annotation-driven

<context:component-scan/>该xml配置作用是启动Spring的组件扫描功能&#xff0c;自动扫描base-package指定的包及其子文件下的java文件&#xff0c;如果扫描到有controller、Service、Repository、Component等注解的java类&#xff0c;就会将这些类注册为bean。指定的包…

“不亦乐乎”是“乐”还是“悦”?

看了六七年的《咬文嚼字》&#xff0c;在2009年的第一期第一次对其内容产生了巨大的质疑。这是《咬文嚼字》2009年第一期特稿&#xff1a;“《2008年十大语文差错》”&#xff0c;里面公布了《咬文嚼字》编辑部总结的2008年度十大语文差错&#xff1a;  一、“有朋自远方来&a…

mysql 数据操作 单表查询 where约束 between and or

WHERE约束 where字句中可以使用&#xff1a; 比较运算符&#xff1a;>< > < !between 80 and 100 值在80到100之间 >80 <100in(80,90,100) 值是80或90或100 满足这个条件就可以like egon%pattern可以是%或_&#xff0c;%表示任意多字符_表示一个字符…