是什麼問題:Socket連接復位仍然沒有完全理解
看起來不合邏輯一個Java Socket技術的基於服務器的程序重置它在已建立連接的中間連接到Java套接字基於客戶端,儘管數據SO_TIMEOUT的設置轉移被設定爲 「無限」
我測試的服務器:
Linux操作系統Ubuntu 14.04 LTS內核3.13.0-29,通用的Java(TM)SE運行時環境(建立1.7.0_03-B04) 和on Windows 8.1版本6.3.9600 Java™SE運行時環境(bui ld 1.7.0_51-b13)
而且有區別。在Windows中,服務器在所有線程繁忙且使用積壓時都不接受連接,所以應該如此。在Linux連接被接受的情況下,數據可以被寫入和刷新(除了TCP_NODELAY),但是在隨後由客戶端讀取時,其現在和接收「連接重置」。我在服務器端沒有任何例外。 如果客戶端在Windows或Linux下運行,在環回地址,本地網絡地址或外部網絡地址上運行服務器時沒有任何變化。
任何幫助或貢獻將是非常受歡迎的。我也在這裏學習,所以如果我犯了編碼錯誤就告訴我。
在之前的文章中,沒有添加源代碼,而沒有鏈接到我的網站上的JAR和源圖片。我同意這在這裏並不常見,所以我提出了一個濃縮版本,它也揭示了這個問題。請注意,所有設置都是故意選擇的,以使服務器處於超載狀態,超時連接和讀取設置爲「無限」。我意識到這些不是在「現實生活」中選擇的人,而只是產生「連接重置」。
這是客戶端的代碼:
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 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
除非您有具體的問題,否則您的帖子超出了本網站的範圍。 –
你能解釋一下爲什麼嗎?我剛剛得到了一個Java編程問題,我用口頭描述。我看到很多人對我遇到的問題都有同樣的問題。 – user3735839
[我可以在這裏問什麼主題?](http://stackoverflow.com/help/on-topic); [我如何問一個好問題?](http://stackoverflow.com/help/how-to-ask) –