Environment:
- OS: [mac os] Version [11.4]
- java version “1.8.0_131”
- junixsocket version 2.4.0
初步怀疑可能是关闭文件描述符的时候存在问题
该问题已经在最新版本2.5.0中修复
1、在server端每次调用accept()方法时,程序的文件描述符列表都会增加一个none的文件描述符。并且在调用close方法后,这个文件描述符没有被关闭。
2、查看调用accept()方法
在代码执行到标记1的时候创建了一个空的文件描述符81
在代码执行到标记2的时候创建了一个指向/tmp/junixsocket-test.socket的文件描述符82
大致可以断定在标记2执行的时候没有关闭标记1中创建的文件描述符
接下来详细看标记2中的代码执行逻辑
①、上图中红色圈出的就是在标记1中创建的空文件描述符
②、在java代码中并没有显式的看到哪里释放了空的文件描述符,不知道在NATIVE方法中是否存在释放的逻辑。需要进一步看Native部分的逻辑实现…
代码部分
client端代码
/**
* A simple demo client.
*
* @author Christian Kohlschütter
* @see UDSServer
*/
public class UDSClient {
final static String udsPath = "/tmp/junixsocket-test.sock";
public static void main(String[] args) throws IOException {
final File socketFile = new File(udsPath);
long start = System.currentTimeMillis();
test2(socketFile);
long end = System.currentTimeMillis();
System.out.println("total = " + (end - start));
}
private static void test2(File socketFile) throws SocketException {
for (int i = 0; i < 100000; i++) {
FactoryArg factoryArg = new FactoryArg(udsPath);
Socket sock = null;
try {
sock = factoryArg.createSocket();
try {
sock.connect(new InetSocketAddress("localhost", 1000));
} catch (SocketException e) {
System.out.println("Cannot connect to server. Have you started it?");
System.out.println();
throw e;
}
System.out.println("Connected");
SocketUtil.clientHandle(sock);
} catch (Exception e) {
e.printStackTrace();
System.out.println("i = " + i);
break;
} finally {
try {
sock.close();
} catch (IOException e) {
e.printStackTrace();
} finally {
System.out.println("client socket has closed!");
}
}
}
}
private static void test1(File socketFile) {
for (int i = 0; i < 100000; i++) {
try (AFUNIXSocket sock = AFUNIXSocket.newInstance()) {
try {
sock.connect(AFUNIXSocketAddress.of(socketFile));
} catch (SocketException e) {
System.out.println("Cannot connect to server. Have you started it?");
System.out.println();
throw e;
}
System.out.println("Connected");
SocketUtil.clientHandle(sock);
} catch (Exception e) {
e.printStackTrace();
System.out.println("i = " + i);
break;
}
}
}
//100000 -> 695857
// 100000 1k -> 154671
}
server端代码
/**
* A simple demo server.
*
* @author Christian Kohlschütter
* @see UDSClient
*/
public final class UDSServer {
private UDSServer() {
throw new UnsupportedOperationException("No instances");
}
public static void main(String[] args) throws IOException {
final File socketFile = new File("/tmp/junixsocket-test.sock");
System.out.println(socketFile);
AFUNIXServerSocket server = null;
try {
server = AFUNIXServerSocket.newInstance();
// server.setReuseAddress(true);
server.bind(AFUNIXSocketAddress.of(socketFile));
System.out.println("server: " + server);
while (!Thread.interrupted()) {
System.out.println("Waiting for connection...");
AFUNIXSocket sock = null;
try {
sock = server.accept();
System.out.println("Connected: " + sock);
SocketUtil.serverhandle(sock);
} catch (IOException e) {
if (server.isClosed()) {
throw e;
} else {
e.printStackTrace();
}
}finally {
if (sock != null) {
sock.close();
}
}
}
}finally {
if (server != null) {
server.close();
}
}
}
}
SocketUtil代码
/**
* @author keweizhang
* @Description
* @create 2022-06-09 11:19
*/
public class SocketUtil {
private static final int MAX_NUMBER = 5;
private static String oneKBString = null;
public static void serverhandle(Socket sock) throws IOException {
InputStream is = null;
OutputStream os = null;
try {
os = sock.getOutputStream();
is = sock.getInputStream();
os.write("Hello, dear Client".getBytes("UTF-8"));
os.flush();
byte[] buf = new byte[128];
int read = is.read(buf);
System.out.println("Client's response: " + new String(buf, 0, read, "UTF-8"));
} finally {
if (is != null) {
is.close();
}
if (os != null) {
os.close();
}
}
}
public static void clientHandle(Socket sock) throws IOException {
InputStream is = null;
OutputStream os = null;
try {
is = sock.getInputStream();
os = sock.getOutputStream();
TimeUnit.MILLISECONDS.sleep(1);
os.write(getOneKB().getBytes("UTF-8"));
os.flush();
byte[] buf = new byte[128];
int read = is.read(buf);
System.out.println("Server says: " + new String(buf, 0, read, "UTF-8"));
} catch (Exception e) {
e.printStackTrace();
} finally {
if (is != null) {
is.close();
}
if (os != null) {
os.close();
}
}
}
public static String getOneKB() {
if (oneKBString == null) {
StringBuffer stringBuffer = new StringBuffer();
for (int i = 0; i < 1024; i++) {
stringBuffer.append("A");
}
stringBuffer.append("\n");
oneKBString = stringBuffer.toString();
}
return oneKBString;
}
}