Использование сокетов для отправки и получения данных
Я использую сокеты для подключения моего приложения Android (клиент) и сервера баз данных Java. От клиента я хотел бы отправлять две переменные данных каждый раз, когда я общаюсь с сервером.
1) Некоторое сообщение (определяемое пользователем через интерфейс)
2) Язык сообщения (определяется пользователем через интерфейс)
Как я могу отправить их так, чтобы сервер интерпретировал их как отдельный объект?
Прочитав данные на стороне сервера и сделав соответствующий вывод, я хотел бы вернуть единственное сообщение клиенту. (Я думаю, что с этим все будет в порядке)
Итак, мои два вопроса: как установить, что две строки, отправляемые (клиент к серверу), уникальны на стороне клиента и как я могу отделить эти две строки на стороне сервера. (Я думал массив строк, но не мог установить, было ли это возможно или целесообразно.)
Я собирался опубликовать код, но я не уверен, как это поможет.
Ответы
Ответ 1
Я полагаю, вы используете TCP-сокеты для взаимодействия клиент-сервер? Один из способов отправки данных различных типов на сервер и обеспечения возможности их различения состоит в том, чтобы выделить первый байт (или более, если у вас более 256 типов сообщений) в качестве некоторого идентификатора. Если первый байт равен единице, то это сообщение A, если его 2, то это сообщение B. Один из простых способов отправить это через сокет - использовать DataOutputStream/DataInputStream
:
Клиент:
Socket socket = ...; // Create and connect the socket
DataOutputStream dOut = new DataOutputStream(socket.getOutputStream());
// Send first message
dOut.writeByte(1);
dOut.writeUTF("This is the first type of message.");
dOut.flush(); // Send off the data
// Send the second message
dOut.writeByte(2);
dOut.writeUTF("This is the second type of message.");
dOut.flush(); // Send off the data
// Send the third message
dOut.writeByte(3);
dOut.writeUTF("This is the third type of message (Part 1).");
dOut.writeUTF("This is the third type of message (Part 2).");
dOut.flush(); // Send off the data
// Send the exit message
dOut.writeByte(-1);
dOut.flush();
dOut.close();
Сервер:
Socket socket = ... // Set up receive socket
DataInputStream dIn = new DataInputStream(socket.getInputStream());
boolean done = false;
while(!done) {
byte messageType = dIn.readByte();
switch(messageType)
{
case 1: // Type A
System.out.println("Message A: " + dIn.readUTF());
break;
case 2: // Type B
System.out.println("Message B: " + dIn.readUTF());
break;
case 3: // Type C
System.out.println("Message C [1]: " + dIn.readUTF());
System.out.println("Message C [2]: " + dIn.readUTF());
break;
default:
done = true;
}
}
dIn.close();
Очевидно, что вы можете отправлять все виды данных, а не только байты и строки (UTF).
Обратите внимание, что writeUTF
записывает измененный формат UTF-8, которому предшествует индикатор длины беззнакового двухбайтового кодированного целого числа, что дает вам 2^16 - 1 = 65535
байтов для отправки. Это позволяет readUTF
найти конец закодированной строки. Если вы выбираете свою собственную структуру записи, вам следует убедиться, что конец и тип записи либо известны, либо обнаружимы.
Ответ 2
Самый простой способ сделать это - обернуть сокеты в ObjectInput/OutputStreams и отправить сериализованные java-объекты. вы можете создавать классы, содержащие соответствующие данные, и вам не нужно беспокоиться о подробных подробностях обработки двоичных протоколов. просто убедитесь, что вы очищаете потоки объектов после того, как вы пишете каждый объект "сообщение".
Ответ 3
//Client
import java.io.*;
import java.net.*;
public class Client {
public static void main(String[] args) {
String hostname = "localhost";
int port = 6789;
// declaration section:
// clientSocket: our client socket
// os: output stream
// is: input stream
Socket clientSocket = null;
DataOutputStream os = null;
BufferedReader is = null;
// Initialization section:
// Try to open a socket on the given port
// Try to open input and output streams
try {
clientSocket = new Socket(hostname, port);
os = new DataOutputStream(clientSocket.getOutputStream());
is = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
} catch (UnknownHostException e) {
System.err.println("Don't know about host: " + hostname);
} catch (IOException e) {
System.err.println("Couldn't get I/O for the connection to: " + hostname);
}
// If everything has been initialized then we want to write some data
// to the socket we have opened a connection to on the given port
if (clientSocket == null || os == null || is == null) {
System.err.println( "Something is wrong. One variable is null." );
return;
}
try {
while ( true ) {
System.out.print( "Enter an integer (0 to stop connection, -1 to stop server): " );
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String keyboardInput = br.readLine();
os.writeBytes( keyboardInput + "\n" );
int n = Integer.parseInt( keyboardInput );
if ( n == 0 || n == -1 ) {
break;
}
String responseLine = is.readLine();
System.out.println("Server returns its square as: " + responseLine);
}
// clean up:
// close the output stream
// close the input stream
// close the socket
os.close();
is.close();
clientSocket.close();
} catch (UnknownHostException e) {
System.err.println("Trying to connect to unknown host: " + e);
} catch (IOException e) {
System.err.println("IOException: " + e);
}
}
}
//Server
import java.io.*;
import java.net.*;
public class Server1 {
public static void main(String args[]) {
int port = 6789;
Server1 server = new Server1( port );
server.startServer();
}
// declare a server socket and a client socket for the server
ServerSocket echoServer = null;
Socket clientSocket = null;
int port;
public Server1( int port ) {
this.port = port;
}
public void stopServer() {
System.out.println( "Server cleaning up." );
System.exit(0);
}
public void startServer() {
// Try to open a server socket on the given port
// Note that we can't choose a port less than 1024 if we are not
// privileged users (root)
try {
echoServer = new ServerSocket(port);
}
catch (IOException e) {
System.out.println(e);
}
System.out.println( "Waiting for connections. Only one connection is allowed." );
// Create a socket object from the ServerSocket to listen and accept connections.
// Use Server1Connection to process the connection.
while ( true ) {
try {
clientSocket = echoServer.accept();
Server1Connection oneconnection = new Server1Connection(clientSocket, this);
oneconnection.run();
}
catch (IOException e) {
System.out.println(e);
}
}
}
}
class Server1Connection {
BufferedReader is;
PrintStream os;
Socket clientSocket;
Server1 server;
public Server1Connection(Socket clientSocket, Server1 server) {
this.clientSocket = clientSocket;
this.server = server;
System.out.println( "Connection established with: " + clientSocket );
try {
is = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
os = new PrintStream(clientSocket.getOutputStream());
} catch (IOException e) {
System.out.println(e);
}
}
public void run() {
String line;
try {
boolean serverStop = false;
while (true) {
line = is.readLine();
System.out.println( "Received " + line );
int n = Integer.parseInt(line);
if ( n == -1 ) {
serverStop = true;
break;
}
if ( n == 0 ) break;
os.println("" + n*n );
}
System.out.println( "Connection closed." );
is.close();
os.close();
clientSocket.close();
if ( serverStop ) server.stopServer();
} catch (IOException e) {
System.out.println(e);
}
}
}