Java 套接字连接重置仍然无法理解
问题是: 看起来,基于Java套接字的服务器程序在建立连接的过程中错误地重置了与基于Java套接字的客户端的连接,尽管数据传输的超时设置被设置为“无限” 我在以下设备上测试了服务器: Linux Ubuntu 14.04 LTS内核3.13.0-29-通用Java(TM)SE运行时环境(build 1.7.0_03-b04) 等等 Windows 8.1版本6.3.9600 Java(TM)SE运行时环境(build 1.7.0_51-b13) 这是有区别的。在Windows上,当所有线程都很忙并且使用了backlog时,服务器不接受连接,因此应该如此。在Linux连接被接受的情况下,数据可以被写入和刷新(除了TCP_NODELAY),但是在客户端的后续读取时,它会不时收到“连接重置”。我在服务器端没有异常。 如果客户端在Windows或Linux下运行,则行为不会发生变化,在环回地址、本地网络地址或外部网络地址上运行服务器也不会有任何区别 欢迎提供任何帮助或贡献。我也是来学习的,所以如果我犯了编码错误,就告诉我 在之前的文章中,除了我网站上的JAR链接和源图片外,没有添加任何源代码。我同意这在这里是不常见的,所以我制作了一个简明的版本,它也揭示了这个问题。请注意,故意选择所有设置以使服务器处于过载状态,并将连接和读取超时设置为“无限”。我确实意识到,这些并不是人们在“现实生活”中会选择的,而仅仅是为了产生“连接重置” 这是客户端的代码:Java 套接字连接重置仍然无法理解,java,multithreading,sockets,Java,Multithreading,Sockets,问题是: 看起来,基于Java套接字的服务器程序在建立连接的过程中错误地重置了与基于Java套接字的客户端的连接,尽管数据传输的超时设置被设置为“无限” 我在以下设备上测试了服务器: Linux Ubuntu 14.04 LTS内核3.13.0-29-通用Java(TM)SE运行时环境(build 1.7.0_03-b04) 等等 Windows 8.1版本6.3.9600 Java(TM)SE运行时环境(build 1.7.0_51-b13) 这是有区别的。在Windows上,当所有线程都很忙
package resetconntest;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.concurrent.Semaphore;
class MiniClient {
static boolean SHOW_EXC_ONLY = true; // show exceptions only
static int THREADS = 64; // number of "simultaneous connections"
static int LOOPS = 256; // total number of connections
static String HOST = "192.168.0.10"; // server hostname
static int PORT = 7272; // server port
static int CONN_TIMEOUT = 0; // keep infinite connect time for test
static int SO_TIMEOUT = 0; // keep infinite read time for test
static int SO_LINGER = -1; // no linger
static boolean REUSE_ADDRESS = false; // chosen for test
static boolean TCP_NODELAY = true; // small blocks, so no Nagle
static boolean KEEP_ALIVE = false; // chosen for test
static int TRAFFIC_CLASS = 0; // if used, use mask as for ToS
public static void main ( String[] args ) {
new MiniClient().runTest ();
System.exit ( 0 );
}
MiniClient () {}
void runTest () {
Object syncer = new Object();
System.out.println ( "--> start MiniClient" );
try {
Semaphore semaphore = new Semaphore ( THREADS );
for ( int x = 0 ; x < LOOPS ; x++ ) {
semaphore.acquireUninterruptibly ();
new Requester ( syncer ,x + 1 ,semaphore ).start();
}
while ( semaphore.availablePermits() < THREADS ) {
Thread.sleep ( 100 );
}
} catch ( Throwable anyThrown ) {
synchronized ( syncer ) {
System.out.println ( "--> throwable in main" );
anyThrown.printStackTrace ( System.out );
System.out.println ( "<-- throwable in main" );
}
}
System.out.println ( "<-- end MiniClient" );
}
class Requester extends Thread {
Object syncer;
String index;
Semaphore semaphore;
Requester ( Object syncer ,int index ,Semaphore semaphore ) {
this.syncer = syncer;
this.index = Integer.toString ( index );
this.semaphore = semaphore;
}
public void run () {
try {
Socket socket = new Socket ();
socket.connect ( new InetSocketAddress ( HOST ,PORT ) ,CONN_TIMEOUT );
socket.setSoTimeout ( SO_TIMEOUT );
socket.setSoLinger ( (SO_LINGER >= 0) ,SO_LINGER );
socket.setReuseAddress ( REUSE_ADDRESS );
socket.setTcpNoDelay ( TCP_NODELAY );
socket.setKeepAlive ( KEEP_ALIVE );
if ( TRAFFIC_CLASS != 0 ) socket.setTrafficClass ( TRAFFIC_CLASS );
PrintWriter out = new PrintWriter ( new OutputStreamWriter ( socket.getOutputStream() ) );
BufferedReader in = new BufferedReader ( new InputStreamReader ( socket.getInputStream() ) );
if ( dialog ( "aaaaa" ,out ,in ) )
if ( dialog ( "bbbbb" ,out ,in ) )
dialog ( "close" ,out ,in );
socket.shutdownInput();
socket.shutdownOutput();
in.close();
out.close();
socket.close ();
} catch ( Throwable anyThrown ) {
synchronized ( syncer ) {
System.out.println ( "--> throwable in client thread:" + index );
anyThrown.printStackTrace ( System.out );
System.out.println ( "<-- throwable in client thread:" + index );
}
}
semaphore.release ();
}
boolean dialog ( String text
,PrintWriter out
,BufferedReader in ) throws Throwable {
String msg = index + ':' + text;
try {
if ( SHOW_EXC_ONLY == false ) synchronized ( syncer ) { System.out.println ( "--> send: " + msg ); }
out.println ( msg );
out.flush();
String resp = in.readLine();
if ( resp == null ) {
synchronized ( syncer ) { System.out.println ( "<-- got EOF after: " + msg ); }
return false;
}
if ( SHOW_EXC_ONLY == false ) synchronized ( syncer ) { System.out.println ( "<-- received: " + resp ); }
} catch ( Throwable anyThrown ) {
synchronized ( syncer ) {
System.out.println ( "--> throwable in client thread:" + index );
System.out.println ( "--> at processing message: " + msg );
anyThrown.printStackTrace ( System.out );
System.out.println ( "<-- at processing message: " + msg );
System.out.println ( "<-- throwable in client thread:" + index );
}
return false;
}
return true;
}
} // end of inner class
} // end of code
package测试;
导入java.io.BufferedReader;
导入java.io.InputStreamReader;
导入java.io.OutputStreamWriter;
导入java.io.PrintWriter;
导入java.net.InetSocketAddress;
导入java.net.Socket;
导入java.util.concurrent.Semaphore;
类小型客户端{
静态布尔值SHOW\u EXC\u ONLY=true;//仅显示异常
static int THREADS=64;//同时连接数
静态int循环=256;//连接总数
静态字符串HOST=“192.168.0.10”;//服务器主机名
静态int-PORT=7272;//服务器端口
static int CONN_TIMEOUT=0;//为测试保留无限连接时间
static int SO_TIMEOUT=0;//为测试保留无限的读取时间
static int SO_LINGER=-1;//无LINGER
静态布尔重用_ADDRESS=false;//选择用于测试
静态布尔值TCP_NODELAY=true;//小块,所以没有Nagle
静态布尔KEEP_ALIVE=false;//选择用于测试
static int TRAFFIC_CLASS=0;//如果使用,请将掩码用作ToS
公共静态void main(字符串[]args){
新的MiniClient().runTest();
系统出口(0);
}
小型客户端(){}
无效运行测试(){
对象同步器=新对象();
System.out.println(“-->start MiniClient”);
试一试{
信号量信号量=新信号量(线程);
for(int x=0;xthrowable in main”);
anythround.printStackTrace(System.out);
System.out.println(“可在客户端线程中丢弃:”+索引);
anythround.printStackTrace(System.out);
System.out.println(“发送:+msg);}
out.println(msg);
out.flush();
字符串resp=in.readLine();
如果(resp==null){
synchronized(syncer){System.out.println(“在处理消息时:“+msg”);
anythround.printStackTrace(System.out);
System.out.println(“启动迷你服务器”);
试一试{
InetSocketAddress socketAddress=新的InetSocketAddress(InetAddress.getByName(主机),端口);
ServerSocket ServerSocket=newserversocket();
serverSocket.bind(socketAddress,BACKLOG);
serverSocket.setReuseAddress(重用服务器地址);
serverSocket.SetSortimeout(ACC_超时);
信号量信号量=新信号量(线程);
接受套接字;
while(true){
信号量。获取不间断();
accepted=serverSocket.accept();
新服务程序(同步器、已接受、信号量).start();
}
//从未到达,在服务器构造时发出警告。
//要结束服务器,只需使用老式的钝器CTRL-C
//while(semaphore.availablePermits()throwable in main”);
anythround.printStackTrace(System.out);
System.out.println(“可在服务器线程中丢弃”);
anythround.printStackTrace(System.out);
System.out.println(“
在服务器和客户机上完全删除这一行。除了我在评论中所说的之外,这是引发连接重置的另一种方式。只需删除它。你不需要它。这是一个问题,不是一个解决方案。除非你有特定问题,否则你的帖子不在本网站的范围内。你能解释一下原因吗?我刚刚有一个Java编程专业人士我口头描述的问题。我看到许多人的帖子与我处理的问题有着相同的问题类型。你的问题以目前的形式无法回答。它包括对你认为应用程序的功能的描述,以及一个指向大量没有人会遵循的场外代码的链接。这不是免费调试g服务
package resetconntest;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.Semaphore;
class MiniServer {
static boolean SHOW_EXC_ONLY = false; // show messages and exceptions
static String HOST = "192.168.0.10"; // host name binded to
static int PORT = 7272; // port number binded to
static int ACC_TIMEOUT = 0; // keep timeout for accept infinite for test
static boolean REUSE_SERVER_ADDRESS = false; // chosen for test
static int BACKLOG = 2; // keep low for test
static int THREADS = 8; // keep low for test
static int SO_TIMEOUT = 0; // keep infinite read timeout for test
static int SO_LINGER = -1; // no lingering
static boolean REUSE_ACC_ADDRESS = false; // chosen for test
static boolean TCP_NODELAY = true; // small blocks, so no Nagle
static boolean KEEP_ALIVE = false; // chosen for test
static int TRAFFIC_CLASS = 0; // if used, use mask as for ToS
static int PROCESS_DELAY = 500; // simulate long message processing 0.5 sec
public static void main ( String[] args ) {
new MiniServer().runTest ();
System.exit ( 0 );
}
MiniServer () {}
public void runTest () {
Object syncer = new Object();
System.out.println ( "--> start MiniServer" );
try {
InetSocketAddress socketAddress = new InetSocketAddress ( InetAddress.getByName ( HOST ), PORT );
ServerSocket serverSocket = new ServerSocket ();
serverSocket.bind ( socketAddress ,BACKLOG );
serverSocket.setReuseAddress ( REUSE_SERVER_ADDRESS );
serverSocket.setSoTimeout ( ACC_TIMEOUT );
Semaphore semaphore = new Semaphore ( THREADS );
Socket accepted;
while ( true ) {
semaphore.acquireUninterruptibly();
accepted = serverSocket.accept();
new Servicer ( syncer ,accepted ,semaphore ).start();
}
// never reached, gives the warning at server construction.
// to end the server, just use the old fashioned blunt CTRL-C
// while ( semaphore.availablePermits() < THREADS ) {
// Thread.sleep ( 100 );
// }
// serverSocket.close ();
} catch ( Throwable anyThrown ) {
synchronized ( syncer ) {
System.out.println ( "--> throwable in main" );
anyThrown.printStackTrace ( System.out );
System.out.println ( "<-- throwable in main" );
}
}
System.out.println ( "<-- end MiniServer" );
}
class Servicer extends Thread {
Object syncer;
Socket socket;
Semaphore semaphore;
Servicer ( Object syncer
,Socket socket
,Semaphore semaphore ) {
this.syncer = syncer;
this.socket = socket;
this.semaphore = semaphore;
}
public void run () {
try {
socket.setSoTimeout ( SO_TIMEOUT );
socket.setSoLinger ( (SO_LINGER >= 0) ,SO_LINGER );
socket.setReuseAddress ( REUSE_ACC_ADDRESS );
socket.setTcpNoDelay ( TCP_NODELAY );
socket.setKeepAlive ( KEEP_ALIVE );
if ( TRAFFIC_CLASS != 0 ) socket.setTrafficClass ( TRAFFIC_CLASS );
BufferedReader in = new BufferedReader( new InputStreamReader ( socket.getInputStream() ) );
PrintWriter out = new PrintWriter ( new OutputStreamWriter ( socket.getOutputStream() ) );
String clientMessage;
while ( true ) {
clientMessage = in.readLine ();
if ( clientMessage == null ) {
synchronized ( syncer) { System.out.println ( "<-> received end of file from accepted socket" ); }
break;
}
if ( SHOW_EXC_ONLY == false ) synchronized ( syncer ) { System.out.println ( "client said: " + clientMessage ); }
if ( PROCESS_DELAY > 0 ) Thread.sleep ( PROCESS_DELAY );
out.println ( "echo: " + clientMessage );
out.flush();
if ( clientMessage.indexOf ( "close" ) >= 0 ) break;
}
socket.shutdownInput();
socket.shutdownOutput();
in.close();
out.close();
socket.close();
} catch ( Throwable anyThrown ) {
synchronized ( syncer ) {
System.out.println ( "--> throwable in server thread" );
anyThrown.printStackTrace ( System.out );
System.out.println ( "<-- throwable in server thread" );
}
}
semaphore.release();
}
} // end of inner class
} // end of code
socket.setSoLinger( (SO_LINGER >= 0) ,SO_LINGER );