java - Golang TCP 客户端不向 Java TCP 服务器发送“流结束”
问题描述
我正在编写一个与 Java TCP 服务器对话的简单 Golang TCP 客户端。
我已成功让我的 Golang 客户端向我的 Java 服务器发送消息。
但是,我的 Java 代码期望End of Stream
(其中inputStream.read()
返回-1
)知道是时候停止读取客户端消息了。
除非我先连接,否则Golang 似乎不会发送End of Stream
消息。connection.Write()
Close()
下面是我的 Java 服务器代码:
package com.mycompany.app;
import com.google.gson.*;
import com.google.common.primitives.Bytes;
import java.io.*;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import java.net.ServerSocket;
import java.net.SocketException;
public class MyApp {
public static void main(String[] args) {
int port = 9000;
// Start listening for messages.
try (ServerSocket serverSocket = new ServerSocket(port)) {
System.out.println("Listening on port " + port + "...");
// Never stop listening for messages.
while (true) {
try {
// Accept a client connection.
Socket socket = serverSocket.accept();
// Read message from the client.
DataInputStream inputStream = new DataInputStream(socket.getInputStream());
List<Byte> list = new ArrayList<Byte>();
int input = inputStream.read();
while (input != -1) {
list.add((byte) input);
input = inputStream.read();
}
byte[] jsonBytes = Bytes.toArray(list);
if (jsonBytes.length > 0) {
String jsonString = new String(jsonBytes);
System.out.println("Received: " + jsonString);
// Unmarshal from JSON.
Person person = new Gson().fromJson(jsonString, Person.class);
System.out.println("Person: " + person.Name + " " + person.Age);
}
} catch (EOFException e) {
// A client has disconnected. Do nothing.
} catch (SocketException e) {
// A client connection has been terminated unexpectedly. Do nothing.
} catch (Exception e) {
e.printStackTrace();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
class Person {
String Name;
int Age;
}
下面是我的 Golang 客户端代码:
package main
import (
"bufio"
"encoding/json"
"fmt"
"net"
"os"
"strings"
)
type Person struct {
Name string
Age int
}
func main() {
reader := bufio.NewReader(os.Stdin)
for {
func() {
// Dial the Java Server.
conn, err := net.Dial("tcp", "localhost:9000")
if err != nil {
fmt.Println(err)
}
defer conn.Close()
fmt.Print("Enter Name: ")
strName, err := reader.ReadString('\n')
strName = strings.TrimSpace(strName)
var person Person
person.Name = strName
person.Age = 18
jsonBytes, err := json.Marshal(person)
if err != nil {
fmt.Println(err)
return
}
// Write our message to the connection.
_, err = conn.Write(jsonBytes)
if err != nil {
fmt.Println(err)
return
}
fmt.Println("Sent: " + string(jsonBytes))
}()
}
}
关于如何告诉 Java 我们已经完成从 Golang 编写消息的任何建议?还是有更好的方法来处理 Java x Golang TCP 客户端-服务器连接?
这是一个相当大的问题,因为 TCP 连接的基本场景之一是发送和接收:
例如
客户端发送消息并等待结果。
服务器处理消息并返回结果。
客户对结果做了一些事情。
解决方案
对于初学者,您可能希望确保您的客户端代码可靠地关闭套接字。但这不是你应该做的全部。
作为关闭套接字的结果,客户端进程应该触发 TCP FIN。并且由于客户端进程干净地退出,套接字应该关闭。不知道为什么这不是你的情况。你等得够久吗?
但是,为了使您的服务器不会无限期挂起,您需要注意这种情况。考虑客户端和服务器之间存在活动 TCP 连接的情况。当服务器在等待来自客户端的数据时,客户端所在的地方就会断电。因为客户端无法发送 FIN,所以服务器连接不会有任何流量。该 TCP 连接将永远挂起,除非......
您可以在服务器端设置保持活动选项或超时选项。
保持活动状态:https ://docs.oracle.com/javase/7/docs/api/java/net/SocketOptions.html#SO_KEEPALIVE
超时:https ://docs.oracle.com/javase/7/docs/api/java/net/SocketOptions.html#SO_TIMEOUT
推荐阅读
- css - Material-UI Autocomplete/Popper - 如何防止 x-scroll
- wordpress - 不匹配的 hreflang 和 HTML 语言声明和规范
- mysql - 根据状态获取用户
- amazon-web-services - 由于 CORS 错误,AWS S3 未与 API Gateway 连接
- windows - 如何从 .bat 文件运行多个服务
- amazon-web-services - 443 以外端口的 AWS 虚拟机 Https
- java - 在 Java 中调用子类的方法而不进行向下转换
- c# - 控制台应用程序中的工厂设计模式实现
- c++ - 发布模式下的 Xcode 无法编译
- 抱怨 __builtin_ia32_emms() - python - 如何根据确切的查询集过滤 Django ManyToManyField?