- Lesson: All About Sockets
- What Is a Socket?
- Reading from and Writing to a Socket
- Writing a Client/Server Pair
- Lesson: All About Sockets
- What Is a Socket?
- Reading from and Writing to a Socket
- Writing a Client/Server Pair
- Using Sockets to send and receive data
- 3 Answers 3
- Обмен данными по сети на основе сокетов в Java
Lesson: All About Sockets
URL s and URLConnection s provide a relatively high-level mechanism for accessing resources on the Internet. Sometimes your programs require lower-level network communication, for example, when you want to write a client-server application.
In client-server applications, the server provides some service, such as processing database queries or sending out current stock prices. The client uses the service provided by the server, either displaying database query results to the user or making stock purchase recommendations to an investor. The communication that occurs between the client and the server must be reliable. That is, no data can be dropped and it must arrive on the client side in the same order in which the server sent it.
TCP provides a reliable, point-to-point communication channel that client-server applications on the Internet use to communicate with each other. To communicate over TCP, a client program and a server program establish a connection to one another. Each program binds a socket to its end of the connection. To communicate, the client and the server each reads from and writes to the socket bound to the connection.
What Is a Socket?
A socket is one end-point of a two-way communication link between two programs running on the network. Socket classes are used to represent the connection between a client program and a server program. The java.net package provides two classes—Socket and ServerSocket—that implement the client side of the connection and the server side of the connection, respectively.
Reading from and Writing to a Socket
This page contains a small example that illustrates how a client program can read from and write to a socket.
Writing a Client/Server Pair
The previous page showed an example of how to write a client program that interacts with an existing server via a Socket object. This page shows you how to write a program that implements the other side of the connection—a server program.
Lesson: All About Sockets
URL s and URLConnection s provide a relatively high-level mechanism for accessing resources on the Internet. Sometimes your programs require lower-level network communication, for example, when you want to write a client-server application.
In client-server applications, the server provides some service, such as processing database queries or sending out current stock prices. The client uses the service provided by the server, either displaying database query results to the user or making stock purchase recommendations to an investor. The communication that occurs between the client and the server must be reliable. That is, no data can be dropped and it must arrive on the client side in the same order in which the server sent it.
TCP provides a reliable, point-to-point communication channel that client-server applications on the Internet use to communicate with each other. To communicate over TCP, a client program and a server program establish a connection to one another. Each program binds a socket to its end of the connection. To communicate, the client and the server each reads from and writes to the socket bound to the connection.
What Is a Socket?
A socket is one end-point of a two-way communication link between two programs running on the network. Socket classes are used to represent the connection between a client program and a server program. The java.net package provides two classes—Socket and ServerSocket—that implement the client side of the connection and the server side of the connection, respectively.
Reading from and Writing to a Socket
This page contains a small example that illustrates how a client program can read from and write to a socket.
Writing a Client/Server Pair
The previous page showed an example of how to write a client program that interacts with an existing server via a Socket object. This page shows you how to write a program that implements the other side of the connection—a server program.
Using Sockets to send and receive data
I am using sockets to connect my Android application (client) and a Java backend Server. From the client I would like to send two variables of data each time I communicate with the server. 1) Some kind of message (Defined by the user through the interface) 2) The language of the message (Defined by the user through the interface) How could I send these so that the server interprets each as a separate entity? Having read the data on the server side and made an appropriate conclusion, I would like to return a single message to the client. (I think I will be okay with this) So my two questions are how can I establish that the two Strings being sent (client to server) are unique on the client side and how can I separate these two Strings on the server side. (I was thinking an array of Strings, but could not establish if this was possible or appropriate.) I was going to post some code but I’m not sure how that would help.
3 Answers 3
I assume you are using TCP sockets for the client-server interaction? One way to send different types of data to the server and have it be able to differentiate between the two is to dedicate the first byte (or more if you have more than 256 types of messages) as some kind of identifier. If the first byte is one, then it is message A, if its 2, then its message B. One easy way to send this over the socket is to use 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();
Obviously, you can send all kinds of data, not just bytes and strings (UTF).
Note that writeUTF writes a modified UTF-8 format, preceded by a length indicator of an unsigned two byte encoded integer giving you 2^16 — 1 = 65535 bytes to send. This makes it possible for readUTF to find the end of the encoded string. If you decide on your own record structure then you should make sure that the end and type of the record is either known or detectable.
Hi Gamer, one little problem. On the server side I am using a ServerSocket rather than just Socket. DataInputStream does not appear to be supported in this case.
How are your clients connecting? I assume you are doing a socket.accept() somewhere to wait for a client to connect? That function returns a Socket that you can call getInputStream and getOutputStream on.
the easiest way to do this is to wrap your sockets in ObjectInput/OutputStreams and send serialized java objects. you can create classes which contain the relevant data, and then you don’t need to worry about the nitty gritty details of handling binary protocols. just make sure that you flush your object streams after you write each object «message».
despite the fact that the message is written a long time ago, I have a question, how can I distinguish between sending String message or List of elements? I posted my [question] (stackoverflow.com/questions/25699232/…)
That’s a terrible idea, you should avoid object serialization just to create a low level protocol such as this. Integers are much better written using DataInputStream / DataOutputStream .
@MaartenBodewes — you’re certainly welcome to your opinion. as with all things in life, programming is a series of trade-offs. you can trade convenience (java serialization) for additional code/complexity (hand written serialization protocol) or for additional libraries with learning curves (json/xml based serialization libs). it all depends where you want to invest your time and effort.
We’re talking about two rather different Java environments here, which are likely not in sync that much. So you could have to work with different versions of different classes. If you ever need to update them then you’d have to make sure that all the clients switch at the same time or work around it using version numbers and such. If you ever want to switch runtimes on the server or the clients then you may have to redo the protocol. Java serialization certainly has it benefits, but I’d mainly use it on tightly controlled systems (between servers in the same farm, for instance).
@MaartenBodewes actually java serialization has lots of builtin support for migrating classes (it is quite powerful and flexible). you can certainly support multiple client versions using java serialization. and writing your own custom serialization protocol using DataInput and DataOutput doesn’t magically solve any of the problems you mentioned.
//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); >> >
Code only comments are generally not well received, please explain what you do above the code; the code should be used to explain the answer; it should not be the answer itself.
Обмен данными по сети на основе сокетов в Java
Передача данных — одна из краеугольных задач информационных технологий. От неё зависит как работа компаний, так и повседневная жизнь обычных людей.
Для решения этой задачи Java предоставляет различные механизмы, среди которых особое место занимают сокеты.
Сокет (англ. socket — разъём) — название программного интерфейса для обеспечения обмена данными между процессами. Процессы при таком обмене могут исполняться как на одной ЭВМ, так и на различных ЭВМ, связанных между собой сетью. Сокет — абстрактный объект, представляющий конечную точку соединения (Википедия).
Ключевое отличие сокетов от других сетевых инструментов Java (таких как HttpRequest, SMTPTransport и др.) состоит в том, что:
- Сокеты представляют собой достаточно низкоуровневый интерфейс.
Это позволяет работать напрямую через протокол TCP/IP и тем самым обеспечивает универсальность. - Сокеты позволяют обеспечить обмен данными в режиме достаточно приближенном к реальному времени.
При отсутствии задержек при обработке и передачи данных обмен происходит с очень высокой скоростью.
Недостаток сокетов, по сути является продолжением их достоинств. Универсальность и работа на низком уровне неизбежно порождает неудобство при работе с распространёнными протоколами (того же HTTP) . Поэтому для них лучше использовать высокоуровневые средства. Но, подобные протоколы, к сожалению, не покрывают весь спектр задач сетевого программирования. Поэтому программирование на сокетах по-прежнему остаётся актуальным.
Ниже мы рассмотрим примеры создания и работы серверных и клиентских сокетов на примере несложного клиент-серверного приложения.
Серверная часть
Существует два вида сокетов. Серверные и клиентские. В этой части мы рассмотрим серверные сокеты.
Серверные сокеты реализуются на основе класса ServerSocket. Они прослушивают определённый порт и по получении данных от клиента могут сформировать и передать ответ.
Ниже приведён пример создания серверного сокета для 5000 порта.