I want use spring integration to replace socket client.My socket client code is like this:
public static void main(String[] args) {
try {
Socket socket = new Socket("localhost", 7779);
OutputStream os = socket.getOutputStream();
PrintWriter pw = new PrintWriter(os);
String str = "hello server!";
pw.write(str);
pw.flush();
socket.shutdownOutput();
InputStream is = socket.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String info = br.readLine();
while (info != null) {
System.out.println("i am client. server says that " + info);
info = br.readLine();
pw.close();
}
br.close();
is.close();
pw.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
socket client will get server's reply msg. and I use spring integration to do the same job. spring integration's xml code is like this:
<int:gateway id="gw"
service-interface="org.springframework.integration.samples.tcpclientserver.SimpleGateway"
default-request-channel="input"/>
<int-ip:tcp-connection-factory id="client"
type="client"
host="localhost"
port="7779"
single-use="true"
so-timeout="10000"/>
<int:channel id="input"/>
<int-ip:tcp-outbound-gateway id="outGateway"
request-channel="input"
reply-channel="clientBytes2StringChannel"
connection-factory="client"
request-timeout="10000"
reply-timeout="10000"/>
<int:object-to-string-transformer id="clientBytes2String"
input-channel="clientBytes2StringChannel"/>
it's a part of spring integration's tcp-client-server example https://github.com/spring-projects/spring-integration-samples/tree/master/basic/tcp-client-server
java code is like this:
final Scanner scanner = new Scanner(System.in);
final GenericXmlApplicationContext context = Main.setupContext();
final SimpleGateway gateway = context.getBean(SimpleGateway.class);
final AbstractServerConnectionFactory crLfServer = context.getBean(AbstractServerConnectionFactory.class);
TestingUtilities.waitListening(crLfServer, 10000L);
while (true) {
final String input = scanner.nextLine();
if ("q".equals(input.trim())) {
break;
}
else {
final String result = gateway.send(input);
System.out.println(result);
}
}
System.out.println("Exiting application...bye.");
System.exit(0);
}
public static GenericXmlApplicationContext setupContext() {
final GenericXmlApplicationContext context = new GenericXmlApplicationContext();
if (System.getProperty(AVAILABLE_SERVER_SOCKET) == null) {
System.out.print("Detect open server socket...");
int availableServerSocket = SocketUtils.findAvailableTcpPort(5678);
final Map<String, Object> sockets = new HashMap<>();
sockets.put(AVAILABLE_SERVER_SOCKET, availableServerSocket);
final MapPropertySource propertySource = new MapPropertySource("sockets", sockets);
context.getEnvironment().getPropertySources().addLast(propertySource);
}
System.out.println("using port " + context.getEnvironment().getProperty(AVAILABLE_SERVER_SOCKET));
context.load("classpath:META-INF/spring/integration/tcpClientServerDemo-context.xml");
context.registerShutdownHook();
context.refresh();
return context;
}
and I can't get sever reply, because server doesn't get a eof signal and it still blocked in readLine(); the exception I get : org.springframework.integration.MessageTimeoutException: Timed out waiting for response.
Here is server code:
try {
ServerSocket serverSocket = new ServerSocket(7779);
Socket socket = serverSocket.accept();
InputStream is = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String info = br.readLine();
System.out.println("from client : "+info);
while (info != null) {
System.out.println("i am server. message from client is " + info);
info = br.readLine(); //server blocked here
}
socket.shutdownInput();
OutputStream os = socket.getOutputStream();
String replyMsg="welcom from server 7779 ACK\r\n";
os.write(replyMsg.getBytes());
os.close();
br.close();
isr.close();
is.close();
socket.close();
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
so how can I send a eof singal to server so my application will get the server's reply?
ByteArrayCrLfSerializer
by default, which adds\r\n
to the data, so thereadLine()
should exit just fine and you are properly adding\r\n
on the reply so that should be received ok too. Try turning on DEBUG logging to see if it helps; also look at a network trace, such as with WireShark. – Gary Russell