Android TWinSocketStream.Read():读取错误6,句柄无效

Android TWinSocketStream.Read():读取错误6,句柄无效,android,multithreading,sockets,delphi,delphi-xe5,Android,Multithreading,Sockets,Delphi,Delphi Xe5,当我关闭与某个客户端的连接时,会发生此错误。错误位于服务器中的此代码行上: Received := SocketStrm.Read(Data, SizeOf(Data)); 此外,当智能手机重新启动时(或者,例如,当我关闭客户端应用程序时),丢失的客户端数据不会从服务器应用程序的列表视图中删除 有人能帮我修复这两个错误吗 以下是我如何发送数据的代码: 客户端(Android): public类MainActivity扩展了AppCompatActivity{ 专用套接字xclientSocke

当我关闭与某个客户端的连接时,会发生此错误。错误位于服务器中的此代码行上:

Received := SocketStrm.Read(Data, SizeOf(Data));
此外,当智能手机重新启动时(或者,例如,当我关闭客户端应用程序时),丢失的客户端数据不会从服务器应用程序的
列表视图中删除

有人能帮我修复这两个错误吗

以下是我如何发送数据的代码:

客户端(Android):

public类MainActivity扩展了AppCompatActivity{
专用套接字xclientSocket;
类ClientThread实现Runnable{
@凌驾
公开募捐{
试一试{
inetAddressServerAddr=InetAddress.getByName(“192.168.15.12”);
xclientSocket=新套接字(serverAddr,101);
新线程(new CMDThread()).start();
}捕获(异常e1){
System.out.println(e1.toString());
}
}
}
类CMDThread实现可运行{
@凌驾
公开募捐{
试一试{
而(xclientSocket.isConnected()){
BufferedReader xreader=新的BufferedReader(新的InputStreamReader(xclientSocket.getInputStream());
DataOutputStream dOut=新的DataOutputStream(xclientSocket.getOutputStream());
字符串xline;
if(xreader.ready()){
而((xline=xreader.readLine())!=null){
系统输出打印LN(xline);
if(xline!=null&&!xline.trim().isEmpty()){
if(xline.equalsIgnoreCase(“信息”)){
DataOutputStream dOut=新的DataOutputStream(xclientSocket.getOutputStream());
dOut.writeChars(“+myDeviceProduct.toUpperCase()+”+myDeviceModel+“+myVersion+”+SIM\u OPNAME+“+SIM\u NUMBER+”句柄无效"如果在释放使用它的
TWinSocketStream
之前关闭了
ClientSocket
的套接字句柄,则会发生错误。例如,当服务器在关闭其套接字的活动线程的内部列表中循环时,会发生这种情况。这是正常行为。只需忽略线程中的错误,然后重试即可退出
ClientExecute()

也就是说,您没有正确使用
TWinSocketStream.Read()
。在这种情况下,您需要在循环中调用
Read()
(在循环之前的第一次调用是错误的,请将其删除),将接收到的数据附加到不断增长的缓冲区中,并在处理之前扫描缓冲区中的完整消息。重复此操作直到断开连接

在客户端断开连接之前,
Received
不会设置为0,但您的客户端已设置为(可能)在服务器断开连接之前向其发送许多邮件。您没有考虑到这种可能性,因此在断开连接之前,您不应该无休止地阅读。当您收到完整的邮件时,停止阅读,处理它,然后返回阅读

至于您的ListView,正如我前面告诉过您的,在线程阻塞模式下不会触发
OnClientDisconnect
事件,因此您需要在退出
ClientExecute()
之前删除ListView项发送许多消息时,您的代码会将每个消息添加到ListView,因此您需要确保删除所有消息,而不仅仅是第一个找到的消息。否则,请确保每个客户端添加的ListView项目不超过一个

此外,您的服务器(可能)可以接受多个客户端,但您假设一次只连接一个客户端。您的工作线程正在访问全局变量,而这些变量实际上应该是线程的本地变量,因此多个客户端不会覆盖彼此的数据

此外,您还有一个较小的争用条件。工作线程向客户端发送
info
命令,主线程发送
disconnect client
命令。您没有同步这些命令,因此存在一个很小的机会窗口,它们可能重叠,从而破坏您的通信

最后,在Java中,
DataOutputStream.writeChars()
以UTF-16格式写出Unicode字符串。在Delphi中,
Char
在D2007和更早版本中是
AnsiChar
,在D2009和更高版本中是
WideChar
。网络通信应该使用UTF-8作为文本,因为它在平台之间是可移植的(没有终端问题),并且通常占用较少的带宽,特别是对于基于拉丁语的语言。您应该编写Android和Delphi代码,以便通过连接强制使用UTF-8

话虽如此,请尝试以下方式:

public类MainActivity扩展了AppCompatActivity{
专用套接字xclientSocket;
类ClientThread实现Runnable{
@凌驾
公开募捐{
试一试{
xclientSocket=新套接字(“192.168.15.12”,101);
新线程(new CMDThread()).start();
}
捕获(异常e1){
System.out.println(e1.toString());
}
}
}
类CMDThread实现可运行{
@凌驾
公开募捐{
试一试{
BufferedReader xreader=新的BufferedReader(新的InputStreamReader(xclientSocket.getInputStream(),StandardCharsets.UTF_8));
DataOutputStream dOut=新的DataOutputStream(新的BufferedOutputStream(xclientSocket.getOutputStream());
而((xline=xreader.readLine())!=null){
系统输出打印LN(xline);