服务器代码:
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(6666);
while (true){
Socket socket = serverSocket.accept();
OutputStream os = socket.getOutputStream();
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os));
bw.write("我是服务器");
bw.close();
os.close();
socket.close();
}
客户端代码:
public static void main(String[] args) throws IOException {
Socket socket = new Socket("127.0.0.1",6666);
System.out.println("111111111");
InputStream is = socket.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String data = null;
while ((data = br.readLine()) != null){
System.out.println(data);
}
br.close();
is.close();
System.out.println("2222222222");
socket.close();
}
这样是没问题的,客户端读出来服务器写入的信息,但是如果客户端有两个数据流的操作就会报错:Exception in thread "main" java.net.SocketException: Socket is closed,网上查了原因是在自己关闭了socket后进行了流的读写操作,但是我是在最后关闭socket的,
出问题的客户端代码:
public static void main(String[] args) throws IOException {
Socket socket = new Socket("127.0.0.1",6666);
OutputStream os = socket.getOutputStream();
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os));
bw.write("我是客户端");
bw.close();
os.close();
System.out.println("111111111");
InputStream is = socket.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String data = null;
while ((data = br.readLine()) != null){
System.out.println(data);
}
br.close();
is.close();
System.out.println("2222222222");
socket.close();
}
这样会成功执行到打印“1111111”,发送给服务器数据成功,接受服务器信息报错
如果把读写顺序反过来:
public static void main(String[] args) throws IOException {
Socket socket = new Socket("127.0.0.1",6666);
InputStream is = socket.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String data = null;
while ((data = br.readLine()) != null){
System.out.println(data);
}
br.close();
is.close();
System.out.println("111111111");
OutputStream os = socket.getOutputStream();
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os));
bw.write("我是客户端");
bw.close();
os.close();
System.out.println("2222222222");
socket.close();
}
这样读数据会成功,写数据就会失败。
为什么客户端对socket只能进行一次读或者写的操作,第二次操作流就会失败?
- Socket编程 TCP方式发送时间有点长
- 客户端发给服务器的Json序列化对象在服务端反序列化之后有一半几率会多一个字符
- C# 用来接收消息的Socket在结束后,接收消息的线程是否会停止并被回收
- 关于socket并发的问题
- Java 如何在建立 Socket 通信后主动向 C#客户端发送信息
以找到原因,多谢@海之殇
在关闭从socket获取的输出流或输出流时,(Out/In)putStream.close()方法会指向(Out/In)putStream的子类Socket(Out/In)putStream的close方法,关闭关联的socket,源码如下:
/**
* Closes the stream.
*/
private boolean closing = false;
public void close() throws IOException {
// Prevent recursion. See BugId 4484411
if (closing)
return;
closing = true;
if (socket != null) {
if (!socket.isClosed())
socket.close();
} else
impl.close();
closing = false;
}
关闭返回的 OutputStream 将关闭关联套接字
while (true){
Socket socket = serverSocket.accept();
OutputStream os = socket.getOutputStream();
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os));
bw.write("我是服务器");
bw.close();
os.close();
都特么关闭了,就是一次while 流程。重新连你就可以再次该过程了。服务器会对应很多这个过程,你需要在accept后开线程。