java socket client example
Cómo leer todo el Inputstream en Server Socket JAVA (3)
El problema que tiene está relacionado con la naturaleza de transmisión TCP.
El hecho de que haya enviado 100 bytes (por ejemplo) desde el servidor no significa que leerá 100 bytes en el cliente la primera vez que lea. Tal vez los bytes enviados desde el servidor llegan en varios segmentos TCP al cliente.
Debe implementar un bucle en el que lea hasta que se reciba todo el mensaje. Permítame proporcionar un ejemplo con DataInputStream
lugar de BufferedinputStream
. Algo muy simple para darte solo un ejemplo.
Supongamos que usted sabe de antemano que el servidor debe enviar 100 bytes de datos.
En el cliente necesitas escribir:
byte[] messageByte = new byte[1000];
boolean end = false;
String dataString = "";
try
{
DataInputStream in = new DataInputStream(clientSocket.getInputStream());
while(!end)
{
int bytesRead = in.read(messageByte);
dataString += new String(messageByte, 0, bytesRead);
if (dataString.length == 100)
{
end = true;
}
}
System.out.println("MESSAGE: " + dataString);
}
catch (Exception e)
{
e.printStackTrace();
}
Ahora, normalmente el tamaño de los datos enviados por un nodo (el servidor aquí) no se conoce de antemano. Luego debe definir su propio protocolo pequeño para la comunicación entre el servidor y el cliente (o cualquiera de los dos nodos) que se comunican con TCP.
Lo más común y simple es definir TLV: Tipo, Longitud, Valor. Así que usted define que cada mensaje enviado desde el servidor al cliente viene con:
- Tipo de indicación de 1 byte (por ejemplo, también podría ser 2 o lo que sea).
- 1 byte (o lo que sea) para la longitud del mensaje
- N bytes para el valor (N se indica en longitud).
Entonces, sabe que debe recibir un mínimo de 2 bytes y con el segundo byte sabe cuántos bytes siguientes necesita leer.
Esto es solo una sugerencia de un posible protocolo. También podría deshacerse de "Tipo".
Entonces sería algo como:
byte[] messageByte = new byte[1000];
boolean end = false;
String dataString = "";
try
{
DataInputStream in = new DataInputStream(clientSocket.getInputStream());
int bytesRead = 0;
messageByte[0] = in.readByte();
messageByte[1] = in.readByte();
int bytesToRead = messageByte[1];
while(!end)
{
bytesRead = in.read(messageByte);
dataString += new String(messageByte, 0, bytesRead);
if (dataString.length == bytesToRead )
{
end = true;
}
}
System.out.println("MESSAGE: " + dataString);
}
catch (Exception e)
{
e.printStackTrace();
}
El siguiente código compila y se ve mejor. Se asume que los dos primeros bytes que proporcionan la longitud llegan en formato binario, en red endianship (big endian). No se enfoca en diferentes tipos de codificación para el resto del mensaje.
import java.nio.ByteBuffer;
import java.io.DataInputStream;
import java.net.ServerSocket;
import java.net.Socket;
class Test
{
public static void main(String[] args)
{
byte[] messageByte = new byte[1000];
boolean end = false;
String dataString = "";
try
{
Socket clientSocket;
ServerSocket server;
server = new ServerSocket(30501, 100);
clientSocket = server.accept();
DataInputStream in = new DataInputStream(clientSocket.getInputStream());
int bytesRead = 0;
messageByte[0] = in.readByte();
messageByte[1] = in.readByte();
ByteBuffer byteBuffer = ByteBuffer.wrap(messageByte, 0, 2);
int bytesToRead = byteBuffer.getShort();
System.out.println("About to read " + bytesToRead + " octets");
//The following code shows in detail how to read from a TCP socket
while(!end)
{
bytesRead = in.read(messageByte);
dataString += new String(messageByte, 0, bytesRead);
if (dataString.length() == bytesToRead )
{
end = true;
}
}
//All the code in the loop can be replaced by these two lines
//in.readFully(messageByte, 0, bytesToRead);
//dataString = new String(messageByte, 0, bytesToRead);
System.out.println("MESSAGE: " + dataString);
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
Estoy usando Java.net en uno de mis proyectos. y escribí un servidor de aplicaciones que obtiene inputStream de un cliente. Pero algunas veces mi InputStream (almacenado en búfer) no puede recibir todo el OutputStream que el cliente envió a mi servidor. ¿Cómo puedo escribir una espera o algo así, que mi InputStream obtiene todo el OutputStream del cliente?
(Mi InputStream no es una cadena)
private Socket clientSocket;
private ServerSocket server;
private BufferedOutputStream outputS;
private BufferedInputStream inputS;
private InputStream inBS;
private OutputStream outBS;
server = new ServerSocket(30501, 100);
clientSocket = server.accept();
public void getStreamFromClient() {
try {
outBS = clientSocket.getOutputStream();
outputS = new BufferedOutputStream( outBS);
outputS.flush();
inBS = clientSocket.getInputStream();
inputS = new BufferedInputStream( inBS );
} catch (Exception e) {
e.printStackTrace();
}
}
Gracias.
Puedes leer tu BufferedInputStream de esta manera. Leerá los datos hasta que llegue al final del flujo, lo que se indica con -1.
inputS = new BufferedInputStream(inBS);
byte[] buffer = new byte[1024]; //If you handle larger data use a bigger buffer size
int read;
while((read = inputS.read(buffer)) != -1) {
System.out.println(read);
// Your code to handle the data
}
int c;
String raw = "";
do {
c = inputstream.read();
raw+=(char)c;
} while(inputstream.available()>0);
InputStream.available () muestra los bytes disponibles solo después de leer un byte, por lo tanto, do .. while