Socket
的方法似乎不像其名称或文档所暗示的那样起作用。例如。我创建了一个客户端套接字来连接远程serversocket。当连接建立时,serversocket.accept()方法返回一个相应的套接字,该套接字来自客户端套接字的getinputstream。但问题是,如果我关闭客户端套接字,服务器上的套接字仍然会为isClosed()
方法返回false;更荒谬的是,服务器上的Socket
InputStream
开始连续返回值,当客户端套接字关闭并且没有向服务器发送输出时不再阻塞。以下是我的代码:
客户代码:
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();
}
}
你能否给我任何关于完全关闭客户端套接字的建议,以便在关闭客户端后我不会继续输入?非常感谢任何帮助!
答案 0 :(得分:2)
关闭另一端套接字后
socket.getInputStream()
仍然获取数据
这可能是因为仍有传输中的数据尚未被读取。关闭连接不会中止待处理的数据传输。但事实证明,它根本没有获得数据。您的代码中只有一个错误。
最近几天我对socket非常不满。
我建议你克服自己心烦意乱并对所选职业采取理性态度。
我发现套接字的方法不能按照其名称或文档的方式起作用。
让我们看看。
例如。我创建了一个客户端套接字来连接远程serversocket。当连接建立时,serversocket.accept()方法返回一个相应的套接字,该套接字来自客户端套接字的getinputstream。但问题是,如果我关闭客户端套接字,服务器上的套接字仍然为
isClosed()
方法返回true
不,它没有。它返回false。服务器的套接字仍处于打开状态。 客户端套接字已关闭,连接也是如此,但isClosed()
会告诉您调用套接字的状态,而不是其他任何内容,特别是不是连接。
更荒谬的是,服务器上的socket.getInputStream()开始连续返回值,当客户端套接字关闭并且没有向服务器发送输出流时,不再阻塞。
仅在对等方关闭之前有飞行数据。否则,这是由于您的代码中存在错误,现在是:
//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);
你能否给我任何关于完全关闭客户端插座的建议,以便在我关闭客户端后不会继续获取输入?
你正在完美地关闭它。问题是你没有在另一端正确检测到它。