我尝试从 Android 手机通过 Socket 发送数据。我将 pdf 文件发送到打印机进行打印。在 Java 中它可以正常工作,但 Kotlin 会抛出 SocketException: sendto failed: EBADF (Bad file Descriptor),但是使用 Kotlin 代码,无论打印什么都可以打印。
完整堆栈跟踪:
java.net.SocketException: sendto failed: EBADF (Bad file descriptor)
at libcore.io.IoBridge.maybeThrowAfterSendto(IoBridge.java:542)
at libcore.io.IoBridge.sendto(IoBridge.java:511)
at java.net.PlainSocketImpl.write(PlainSocketImpl.java:500)
at java.net.PlainSocketImpl.-wrap1(PlainSocketImpl.java)
at java.net.PlainSocketImpl$PlainSocketOutputStream.write(PlainSocketImpl.java:266)
at java.io.OutputStream.write(OutputStream.java:82)
at java.io.DataOutputStream.writeBytes(DataOutputStream.java:156)
at com.example.print.printerserver.connectors.OutputHelper.writeFooter(OutputHelper.java:22)
at com.example.print.printerserver.connectors.PrinterConnector.fillPJL(PrinterConnector.kt:30)
at com.example.print.printerserver.connectors.PrinterConnector.access$fillPJL(PrinterConnector.kt:8)
at com.example.print.printerserver.connectors.PrinterConnector$print$1.subscribe(PrinterConnector.kt:17)
at io.reactivex.internal.operators.single.SingleCreate.subscribeActual(SingleCreate.java:39)
at io.reactivex.Single.subscribe(Single.java:2779)
at io.reactivex.internal.operators.single.SingleSubscribeOn$SubscribeOnObserver.run(SingleSubscribeOn.java:89)
at io.reactivex.Scheduler$DisposeTask.run(Scheduler.java:452)
at io.reactivex.internal.schedulers.ScheduledRunnable.run(ScheduledRunnable.java:61)
at io.reactivex.internal.schedulers.ScheduledRunnable.call(ScheduledRunnable.java:52)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:269)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
at java.lang.Thread.run(Thread.java:818)
Caused by: android.system.ErrnoException: sendto failed: EBADF (Bad file descriptor)
at libcore.io.Posix.sendtoBytes(Native Method)
at libcore.io.Posix.sendto(Posix.java:211)
at libcore.io.BlockGuardOs.sendto(BlockGuardOs.java:278)
at libcore.io.IoBridge.sendto(IoBridge.java:509)
抛出异常的代码:
return Single.create<String> { emitter ->
try {
Socket(ip, port).use { socket ->
DataOutputStream(socket.getOutputStream()).use { output ->
fillPJL(output, filename, paperSize, copies)
emitter.onSuccess("Success printing")
}
}
} catch (e: Exception) {
emitter.onError(e)
}
}
我的相同 Java 示例(使用 PJL 命令):
return Single.create(new SingleOnSubscribe<String>() {
@Override
public void subscribe(SingleEmitter<String> emitter) throws Exception {
Socket socket = null;
DataOutputStream out = null;
FileInputStream inputStream = null;
try {
socket = new Socket(printerIP, printerPort);
out = new DataOutputStream(socket.getOutputStream());
DataInputStream input = new DataInputStream(socket.getInputStream());
inputStream = new FileInputStream(file);
byte[] buffer = new byte[3000];
final char ESC = 0x1b;
final String UEL = ESC + "%-12345X";
final String ESC_SEQ = ESC + "%-12345\r\n";
out.writeBytes(UEL);
out.writeBytes("@PJL \r\n");
out.writeBytes("@PJL JOB NAME = '" + filename + "' \r\n");
out.writeBytes("@PJL SET PAPER=" + paperSize.name());
out.writeBytes("@PJL SET COPIES=" + copies);
out.writeBytes("@PJL ENTER LANGUAGE = PDF\r\n");
while (inputStream.read(buffer) != -1)
out.write(buffer);
out.writeBytes(ESC_SEQ);
out.writeBytes("@PJL \r\n");
out.writeBytes("@PJL RESET \r\n");
out.writeBytes("@PJL EOJ NAME = '" + filename + "'");
out.writeBytes(UEL);
out.flush();
} catch (IOException e) {
e.printStackTrace();
emitter.onError(e);
} finally {
try {
if (inputStream != null)
inputStream.close();
if (out != null)
out.close();
if (socket != null)
socket.close();
emitter.onSuccess("Succ");
} catch (IOException e) {
e.printStackTrace();
emitter.onError(e);
}
}
}
});
我的 fillPJL 函数:
private fun fillPJL(output: DataOutputStream?, filename: String, paperSize: PaperSize, copies: Int) {
val ESC = 0x1b.toChar()
val UEL = ESC + "%-12345X"
val ESC_SEQ = ESC + "%-12345\r\n"
output?.writeBytes(UEL)
output?.writeBytes("@PJL \r\n")
output?.writeBytes("@PJL JOB NAME = '$filename' \r\n")
output?.writeBytes("@PJL SET PAPER=" + paperSize.name)
output?.writeBytes("@PJL SET COPIES=" + copies)
output?.writeBytes("@PJL ENTER LANGUAGE = PDF\r\n")
writeData(output)
output?.writeBytes(ESC_SEQ)
output?.writeBytes("@PJL \r\n")
output?.writeBytes("@PJL RESET \r\n")
output?.writeBytes("@PJL EOJ NAME = '\$filename'")
output?.writeBytes(UEL)
}
我将数据写入文件:
fun writeData(output: DataOutputStream) {
file.inputStream().use { input ->
outputStream.use { it.write(input.readBytes()) }
}
}
最佳答案
我解决了我的问题。为了在 Kotlin 中将数据写入 OutputStream,我使用了:
file.inputStream().use { input ->
outputStream.use { it.write(input.readBytes()) }
}
Operator .use { }
在这段代码之后关闭了我的 OutputStream,但后来我再次使用了它。这是异常的原因。
我更改了将数据写入 OutputStream 的方式:
file.inputStream().use { it.copyTo(outputStream, bufferSize = BUFFER) }
它工作正常!!!
关于java - 套接字异常 : sendto failed: EBADF (Bad file descriptor),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48000853/