gpt4 book ai didi

java - 当我关闭另一端套接字后,套接字的输入流仍然获取数据

转载 作者:行者123 更新时间:2023-12-02 03:25:13 25 4
gpt4 key购买 nike

Socket 的方法似乎并不按照其名称或文档所暗示的方式运行。例如。我创建一个客户端套接字来连接远程服务器套接字。当连接建立时,serversocket.accept()方法返回一个相应的套接字,从客户端套接字获取输入流。但问题是,如果我关闭客户端套接字,服务器上的套接字对于 isClosed() 方法仍然返回 false;而且,更荒谬的是,当客户端套接字关闭并且不向服务器发送任何输出时,服务器上的 SocketInputStream 开始连续返回值并且不再阻塞。下面是我的代码:

客户端代码:

public class MainActivity extends AppCompatActivity {
private Button startButton, stopButton;
public byte[] buffer;
public Socket socket;
public Socket tempSocket;
private int port = 50005;
InetSocketAddress address;
private int r_port = 50006;
AudioRecord recorder;
AudioTrack audioTrack;
private int sampleRate = 16000; // 44100 for music
private int channelConfig = AudioFormat.CHANNEL_IN_MONO;
private int audioFormat = AudioFormat.ENCODING_PCM_16BIT;
int minBufSize = AudioRecord.getMinBufferSize(sampleRate, channelConfig, audioFormat);
public static boolean s_status = true;
public static boolean r_status = true;
Thread r_Thread;
Thread s_Thread;
private boolean isPlay = true;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
startButton = (Button) findViewById(R.id.start_button);
startButton.setOnTouchListener(talkListener);
if (socket == null) {
socket = new Socket();
address = new InetSocketAddress("192.168.0.2", port);
try {
socket.setReuseAddress(true);
System.out.println("connecting-");
} catch (IOException e) {
e.printStackTrace();
}
}
}

private final View.OnTouchListener talkListener = new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {

case MotionEvent.ACTION_DOWN:
startButton.setBackgroundColor(Color.parseColor("#0670c0"));
try {

startStreamings();
} catch (Exception e) {
e.printStackTrace();
}
return true; // if you want to handle the touch event

case MotionEvent.ACTION_UP:
startButton.setBackgroundColor(Color.parseColor("#353535"));

try {
s_status = false;

} catch (Exception e) {
e.printStackTrace();

return true; // if you want to handle the touch event
}
}
return false;
}
};
public void startStreamings(){
s_status=true;
buffer = new byte[minBufSize];
s_Thread = new Thread(new Runnable() {

@Override
public void run() {

if (socket == null) {
try {
socket = new Socket();
socket.setReuseAddress(true);

} catch (IOException e) {
e.printStackTrace();
}
}
if (!socket.isConnected()) {
try {
socket.connect(address);
System.out.println("create new connection in startStreaming");
} catch (IOException e) {
e.printStackTrace();
}
}
recorder = new AudioRecord(MediaRecorder.AudioSource.MIC, sampleRate, channelConfig, audioFormat, minBufSize * 10);
try {
if (s_status == true) {
recorder.startRecording();
}
} catch (IllegalStateException e) {
e.printStackTrace();
return;
}

OutputStream os = null;
while (s_status == true) {

//reading data from MIC into buffer
recorder.read(buffer, 0, buffer.length);
try {
os = socket.getOutputStream();
os.write(buffer, 0, minBufSize);
} catch (Exception e) {
e.printStackTrace();
s_status = false;
}
//System.out.println("streaming out: " + buffer.length + "fff" + c++);
}

if (recorder != null) {
recorder.stop();
recorder.release();
recorder = null;
}
}
});
s_Thread.start();
}

}

服务器代码:

    public TcpServerSocket(){

}

public static void main(String args[]) throws Exception {
ServerSocket serverSocket = new ServerSocket(port);
sockets = new ArrayList<Socket>();
while(isListenning){

Socket socket = serverSocket.accept();
isMatched = false;
for(int i =0;i<sockets.size();i++){
Socket preSocket = sockets.get(i);
if(preSocket.getInetAddress().equals(socket.getInetAddress())){
sockets.remove(preSocket);
sockets.add(socket);
isMatched = true;
}
}

if(!isMatched){
sockets.add(socket);
socket.setKeepAlive(false);
new Thread(new TcpServerSocket(socket)).start();
System.out.println("new Connection");
}


}
serverSocket.close();



}

@Override
public void run() {


byte[] receiveData = new byte[1280];
byte[] emptyData = new byte[1280];
InputStream baiss = null;

OutputStream os;
while (isRunning){
try {
baiss = csocket.getInputStream();

if(csocket.isClosed()||!csocket.isConnected()){
isRunning = false;
sockets.remove(csocket);
System.out.println("socket closed!");
}


int numOfBytes = baiss.read(receiveData);
if(numOfBytes==-1){
isRunning=false;
sockets.remove(csocket);
csocket.close();
System.out.println("socket closed!");
}

} catch (IOException e) {
sockets.remove(csocket);
System.out.println("socket closed!");
e.printStackTrace();
}
int socketsLen = sockets.size();
for(int i = 0;i<socketsLen;i++){
Socket client = sockets.get(i);

if(!client.getInetAddress().equals(csocket.getInetAddress())){
try {
os = client.getOutputStream();
os.write(receiveData,0,1280);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

}else if(!client.equals(csocket)){
csocket = client;
System.out.println("switched!");
}
}

System.out.println(csocket.getInetAddress().toString()+"fff"+socketsLen);
}
try {
baiss.close();
csocket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}


}

你们能给我一些建议来完美地关闭客户端套接字,这样我在关闭客户端后就不会继续收到输入吗?非常感谢任何帮助!

最佳答案

socket.getInputStream() still get data after I closed the other side socket

这可能是因为仍有传输中的数据尚未读取。关闭连接不会中止挂起的数据传输。但事实证明,它根本没有获取数据。您的代码中只是存在一个错误。

I am really upset with socket in recent days.

我建议你克服不安,以理性的态度对待你所选择的职业。

I find socket's methods just do not function in the way their names or documentations suggest.

让我们看看。

For example. I create a client socket to connect a remote serversocket. When the connection establishes,the serversocket.accept() method returns a corresponding socket which to getinputstream from the client socket. But the problem is, if I close the client socket, the socket on the server still returns true for the isClosed() method

不,没有。它返回 false。服务器的套接字仍然打开。 客户端套接字已关闭,连接也已关闭,但 isClosed() 告诉您调用它的套接字的状态,而不是其他任何内容,特别是不连接。

and more absurd, the socket.getInputStream() on the server starts to continuously return value and no longer blocks when the client socket has closed and sending no outputstream to the server.

仅当对等方关闭之前有数据正在传输时。否则,这是由于代码中的错误所致,如下所示:

//reading data from MIC into buffer
recorder.read(buffer, 0, buffer.length);

read() 在流末尾返回 -1,并且您忽略它。 这就是为什么你会得到一个连续的循环。这段代码的正确写法如下:

int count = recorder.read(buffer, 0, buffer.length);
if (count == -1) {
recorder.close();
socket.close();
break;
}
try {
os = socket.getOutputStream();
os.write(buffer, 0, count);

您的客户端代码也有类似的问题。您似乎并不关心流结束:

baiss = csocket.getInputStream();
if(csocket.isClosed()||!csocket.isConnected()){
isRunning = false;
sockets.remove(csocket);
System.out.println("socket closed!");
}
baiss.read(receiveData);
// ...
os = client.getOutputStream();
os.write(receiveData,0,1280);

正确的写法如下:

baiss = csocket.getInputStream();
int count = baiss.read(receiveData);
if(count == -1){
isRunning = false;
sockets.remove(csocket);
System.out.println("socket closed!");
}
// ...
os = client.getOutputStream();
os.write(receiveData, 0, count);

Can you guys give me any suggestions to close the client socket perfectly so I won't keep getting input after I close the client?

你完美地关闭了它。问题是您没有在另一端正确检测到它。

关于java - 当我关闭另一端套接字后,套接字的输入流仍然获取数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39030441/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com