2015-04-20 26 views
7
Socket socket = new Socket("192.168.178.47", 82); 

OutputStream out = socket.getOutputStream(); 
out.write("{ \"phone\": \"23456789\" }".getBytes()); 
out.flush(); 

// serwerJava OutputStream opróżnia jedynie dane na ścisłej

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"); 

ja próbuje wysłać dane przez OutputStream do gniazda, ale dane nie są uderzenia gorąca. Jeśli dodam do końca końcówkę out.close();, działa ona idealnie, ale gniazdo jest zamknięte i nie mogę zaakceptować odpowiedzi. Czy ktoś wie dlaczego? Serwer nie podaje żadnego rodzaju błędu. Użyłem Java 1.7!

+0

Jak wygląda kod serwera? – Dan

+0

W jaki sposób potwierdziłeś, że dane wyjściowe nie zostały wysłane? – Simon

+1

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

Odpowiedz

6

Jest możliwe, że serwer czeka na koniec linii. Jeśli jest to przypadek dodać „\ n” do tekstu

+0

To było dokładnie to, co robił mój program. Dzięki za wskazówkę! – gdawgrancid

1

Spróbuj użyć

socket.setTcpNoDelay(true); 

Jest buforowania, który występuje ze względu na wydajność (przeczytać na algorytm nagle'a).

+0

Wielkie umysły :) Próbowałem napisać przed tobą, ale ta strona zaczęła iść naprawdę powoli (inne strony były w porządku). – Dan

0

Patrząc na twój kod wydaje się, że jest OK. Jednakże wysyłacie mniej niż MTU Nagle's algothrim może zatrzymać go, dopóki wystarczająca ilość danych nie będzie dostępna dla pełnego pakietu lub zamkniecie gniazda.

Więc - spróbuj tego:

socket.setTCPNoDelay(true); 

http://en.wikipedia.org/wiki/Nagle%27s_algorithm https://docs.oracle.com/javase/8/docs/api/java/net/Socket.html#setTcpNoDelay-boolean-

+0

Nie działa w ogóle:/ – Neatoro

+0

Miałem na myśli, ale ta strona zajęła mi 5 minut, aby pozwolić mi ją edytować. – Dan

+0

Spróbuj także dopełnić swój ciąg do> 1500 bajtów. To by to udowodniło. – Dan

0

Jest to problem z serwerem, ponieważ flush zawsze zmusić do pisania. przetestować to spróbuj uruchomić ten kod:

public static void main(String[] args) throws IOException, InterruptedException { 
    Socket socket = new Socket("localhost", 8222); 
    OutputStream out = socket.getOutputStream(); 
    for (int i = 0; i < 10; i++) { 
     out.write((i + " : { \"phone\": \"23456789\" }").getBytes()); 
     out.flush(); 
     TimeUnit.SECONDS.sleep(1); 
    } 
} 

wcześniej uruchomić to polecenie na muszli:

$ nc -l localhost 8222 

który nasłuchuje na porcie 8222 dla danych. widać, że co 1 sekundę dane są pokazane na nc wyjściu

3

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
+0

Nie można wysłać -1 z kodu klienta. Czyta w jednym bajcie. Dopóki połączenie nie zostanie zamknięte, może odbierać wartości tylko od 0 do 255. Jeśli klient wywołał 'out.write (-1)' serwer otrzymałby 255. – SpiderPig

+0

@SpiderPig Szczerze mówiąc, nie byłem naprawdę pewny. Mam niewyraźne wspomnienia z robienia tego w przeszłości, ale pewnie pamiętam, że to źle. To, co powiedziałeś, ma sens. Aktualizuję moją odpowiedź, aby to odzwierciedlić. – MadConan

0

Problemem nie jest to, że nie są zaczerwienienie prawidłowo, ale że kod czytanie czeka na gniazdo odłączyć przed dotknięciem dane:

while((i = in.read()) >= 0)

Will pętli tak długo jak coś można odczytać od in (wejście InputStream). Warunek nie zawiedzie, dopóki drugi uczestnik się nie rozłączy.