nie jestem pewien co do etykietowania „// serwer” w swoim pytaniu, ale jestem przy założeniu, że podany kod jest kod serwera:
InputStream in = client.getInputStream();
ByteArrayOutputStream bOut = new ByteArrayOutputStream();
int i = 0;
while((i = in.read()) >= 0) {
bOut.write(i);
}
String complete = new String(bOut.toByteArray(), "UTF-8");
To będzie nadal czytać, blokując za każdym razem, dopóki nie uzyska wartości od read()
mniejszej niż zero. Dzieje się tak tylko wtedy, gdy strumień jest zamknięty.
Wygląda na to, że trzeba ustanowić własny protokół. Zamiast szukać "< = 0" poszukaj jakiejś stałej wartości, która sygnalizuje koniec wiadomości.
Oto krótka demonstracja tego, co mam na myśli (nie miałem czasu wczoraj). Mam 3 klasy, Message
, MyClient
(która także jest klasą main
) i MyServer
. Zauważ, że nic nie jest związane z wysyłaniem lub otrzymywaniem nowej linii. Nic nie ustawia tcpNoDelay. Ale działa dobrze. Niektóre inne uwagi:
- Ten kod wysyła i odbiera tylko jedno żądanie i odpowiedź.
- Nie obsługuje wysyłania wielu instancji
Message
. To wymagałoby sprawdzenia początku Message
oraz końca.
Message
klasa:
public class Message {
public static final String MSG_START = "<message>";
public static final String MSG_END = "</message>";
private final String content;
public Message(String string){
content = string;
}
@Override
public String toString(){
return MSG_START + content + MSG_END;
}
}
MyServer
klasa
public class MyServer implements Runnable{
public static final int PORT = 55555;
@Override
public void run(){
try {
ServerSocket serverSocket = new ServerSocket(PORT);
Socket socket = serverSocket.accept();
String message = getMessage(socket);
System.out.println("Server got the message: " + message);
sendResponse(socket);
}catch (IOException e){
throw new IllegalStateException(e);
}
}
private void sendResponse(Socket socket) throws IOException{
Message message = new Message("Ack");
System.out.println("Server now sending a response to the client: " + message);
OutputStream out = socket.getOutputStream();
out.write(message.toString().getBytes("UTF-8"));
}
private String getMessage(Socket socket) throws IOException{
BufferedInputStream in = new BufferedInputStream(socket.getInputStream());
StringBuilder sb = new StringBuilder(100);
byte[] bytes = new byte[1024<<8];
while(sb.lastIndexOf(Message.MSG_END) == -1){
int bytesRead = in.read(bytes);
sb.append(new String(bytes,0,bytesRead,"UTF-8"));
}
return sb.toString();
}
}
MyClient
klasa
public class MyClient {
public static void main(String[] args){
MyClient client = new MyClient();
Thread server = new Thread(new MyServer());
server.start();
client.performCall();
}
public void performCall(){
try {
Socket socket = new Socket("127.0.0.1",MyServer.PORT);
sendMessage(socket, "Why hello there!");
System.out.println("Client got a response from the server: " + getResponse(socket));
} catch (IOException e) {
throw new IllegalStateException(e);
}
}
public String getResponse(Socket socket) throws IOException{
String response;
StringBuilder sb = new StringBuilder(100);
InputStream in = socket.getInputStream();
byte[] bytes = new byte[1024];
while(sb.lastIndexOf(Message.MSG_END) == -1){
int bytesRead = in.read(bytes);
sb.append(new String(bytes,0,bytesRead,"UTF-8"));
}
response = sb.toString();
return response;
}
public void sendMessage(Socket socket, String message) throws IOException{
Message msg = new Message(message);
System.out.println("Client now sending message to server: " + msg);
OutputStream out = socket.getOutputStream();
out.write(msg.toString().getBytes("UTF-8"));
}
}
Wyjście
Client now sending message to server: Why hello there!
Server got the message: Why hello there!
Server now sending a response to the client: Ack
Client got a response from the server: Ack
Process finished with exit code 0
Jak wygląda kod serwera? – Dan
W jaki sposób potwierdziłeś, że dane wyjściowe nie zostały wysłane? – Simon
No wiesz, 'OutputStream' ma' .flush() '. Poza tym sposób, w jaki piszesz JSON, jest zepsuty: używa domyślnego kodowania JRE. Dlaczego zamiast tego używasz biblioteki JSON? – fge