summary
Java and C#, can use UDP and TCP protocols for network communication. This chapter only describes the basic use of UDP and TCP. Compared with various standard / non-standard TCP, ModbusTCP (occupying 502 port) and lower computer custom network communication protocols required when writing the upper computer, Java TCP and UDP programming is particularly simple.
This chapter only briefly explains the network foundation. The B/S architecture, C/S architecture, OSI7 layer model, TCP5 layer model, three handshakes and four waves of TCP, routers and switches are described in separate chapters.
Network foundation
This chapter only briefly explains the B/S architecture, C/S architecture, OSI7 layer model, TCP5 layer model, three handshakes and four waves of TCP, routers and switches, which are described in separate chapters.
Take a pit first. Insert hyperlink supplement in the future.
Network debugging assistant:
UDP
brief introduction
UDP is a connectionless protocol, similar to broadcast, with high transmission efficiency, but packet loss and unreliability. It is often used in live broadcast, call and other occasions with low reliability requirements.
Workflow
The UDP receiver is turned on first, and the UDP sender is turned on later. After the sender sends data, the receiver can receive data.
Single sending and receiving
First establish the receiving end:
//Test UDP receiver public class ReceiveDemo { public static void main(String[] args) throws IOException { //Create the receiving socket first DatagramSocket datagramSocket = new DatagramSocket(10086);//The receiving socket needs to write the port number //Prepare container byte[] buf = new byte[1024];//Maximum 64Kb data volume of UDP words DatagramPacket datagramPacket = new DatagramPacket(buf, buf.length); //receive data datagramSocket.receive(datagramPacket); //Display data System.out.println(new String(buf, 0, datagramPacket.getLength())); //Release resources datagramSocket.close(); } }
Re establish the sender:
//Test UDP sender public class SendDemo { public static void main(String[] args) throws IOException { //Create sender socket DatagramSocket datagramSocket = new DatagramSocket();//The sending socket does not need to write the port number //Create send data container byte[] bytes = "Ha ha ha ha".getBytes(); DatagramPacket datagramPacket = new DatagramPacket(bytes, bytes.length, InetAddress.getByName("127.0.0.1"),10086); //Note: the IP and port should be written correctly. IP=127.0.0.1 (representing localhost), which is mistakenly written as 121.0.0.1 and cannot communicate //send data datagramSocket.send(datagramPacket); //Release resources datagramSocket.close(); } }
Obviously, you have to open the receiving end first and then open the development sending end to see whether the reception is successful:
Ha ha ha ha Process finished with exit code 0
The receiver displays the result correctly.
Multiple sending and receiving
In fact, the receiving end needs an endless loop to continuously perform the operation of receiving data:
//UDP dead loop receiver public class ReceiveDemo { public static void main(String[] args) throws IOException { //UDP receive data //Create receiver socket DatagramSocket datagramSocket = new DatagramSocket(10086); byte[] buf = new byte[1024]; //receive data //Use while loop while (true){ DatagramPacket datagramPacket = new DatagramPacket(buf, buf.length); datagramSocket.receive(datagramPacket); int length = datagramPacket.getLength(); String data = new String(buf,0,length); System.out.println("data = " + data); //Encounter EXIT! End dead cycle if("EXIT!".equals(data)){ System.out.println("Ready to end"); break; } } System.out.println("end"); //Release resources datagramSocket.close(); } }
Another dead cycle to read keyboard data:
//UDP dead loop sender public class SendDemo { public static void main(String[] args) throws IOException { //UDP send data //Create sender socket DatagramSocket datagramSocket = new DatagramSocket(); //Create data //Create keyboard entry information Scanner sc = new Scanner(System.in); String data; InetAddress localhost = InetAddress.getByName("127.0.0.1");//Cannot new while (true) {//Use the while loop to receive the input data (EXIT! End) System.out.println("Enter the data to be sent:"); //send data data = sc.nextLine(); //Create container byte[] bytes = data.getBytes(); DatagramPacket datagramPacket = new DatagramPacket(bytes, bytes.length, localhost, 10086); datagramSocket.send(datagramPacket); if("EXIT!".equals(data)){ System.out.println("Ready to end"); break; } } System.out.println("end"); //Release resources datagramSocket.close(); } }
The author uses [EXIT!] End the loop. Execute the receiving end first and then the sending end. The effect of the sending end is as follows:
Enter the data to be sent: ha-ha Enter the data to be sent: hshs Enter the data to be sent: hshshsss Enter the data to be sent: EXIT! Ready to end end Process finished with exit code 0
Receiver effect:
data = ha-ha data = hshs data = hshshsss data = EXIT! Ready to end end Process finished with exit code 0
TCP
brief introduction
TCP is a connection oriented communication protocol with its own verification and good reliability.
Workflow
TCPServer starts first and TCPClient starts later. Each time you send data, you need to shake hands 3 times and wave hands 4 times (relevant methods have been encapsulated in Java, so you don't need to care about some details).
Single sending and receiving
First establish TCPServer:
//TCP server public class ServerDemo { public static void main(String[] args) throws IOException { //Create server socket ServerSocket serverSocket = new ServerSocket(10086); //Call accept to block listening Socket socket = serverSocket.accept(); //Get input stream InputStream inputStream = socket.getInputStream(); System.out.println("Server opened"); //Display data //while (true){ byte[] buf = new byte[1024]; int len = inputStream.read(buf); System.out.println("Data received:"+new String(buf,0,len)); //} //Generally, the server does not need to release resources socket.close(); serverSocket.close(); System.out.println("The server has been shut down"); } }
Then create TCPClient:
//TCP Client public class ClientDemo { public static void main(String[] args) throws IOException { //Create socket Socket socket = new Socket("127.0.0.1", 10086); //Get output stream OutputStream os = socket.getOutputStream(); System.out.println("The client starts writing data"); //Write data to pipeline os.write("TCP".getBytes()); //Release resources socket.close(); System.out.println("Close client"); } }
The consequence of incorrect start sequence in UDP is that data cannot be received. If the start sequence in TCP is incorrect, an error will be reported directly:
Exception in thread "main" java.net.ConnectException: Connection refused: connect at java.net.DualStackPlainSocketImpl.connect0(Native Method) at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:79) at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350) at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206) at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188) at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172) at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392) at java.net.Socket.connect(Socket.java:606) at java.net.Socket.connect(Socket.java:555) at java.net.Socket.<init>(Socket.java:451) at java.net.Socket.<init>(Socket.java:228) at com.at.d20210409.Demo3.ClientDemo.main(ClientDemo.java:11) Process finished with exit code 1
Start TCPServer first, and then TCPClient. Client effect:
The client starts writing data Close client Process finished with exit code 0
Server effect:
Server opened Data received: TCP The server has been shut down Process finished with exit code 0
Two way communication
Set up the Server first:
//TCP server with sending function (two-way communication) public class ServerDemo { public static void main(String[] args) throws IOException { //Create server socket object ServerSocket serverSocket = new ServerSocket(10010); //Blocking listening Socket socket = serverSocket.accept(); //Create an input stream to receive data and display it InputStream in = socket.getInputStream(); byte[] buf = new byte[1024]; int len = in.read(buf); System.out.println("The server receives:"+new String(buf,0,len)); //Create output stream and output message OutputStream os = socket.getOutputStream(); os.write("Server receiving completed".getBytes()); //Generally, the server does not need to release resources socket.close(); serverSocket.close(); } }
To create a Client again:
//TCP client with receiving function (two-way communication) public class ClientDemo { public static void main(String[] args) throws IOException { //Create client socket Socket socket = new Socket("127.0.0.1", 10010); //Create output stream output data socket.getOutputStream().write("Say hello to the server".getBytes()); //Create input stream input data InputStream in = socket.getInputStream(); byte[] buf = new byte[1024]; int len = in.read(buf); System.out.println("Data received by client:" + new String(buf, 0, len)); //Release resources socket.close(); } }
After execution in the correct order, the client effect:
The client receives data: the server receives data Process finished with exit code 0
Server effect:
The server receives: say hello to the server Process finished with exit code 0
Multiple sending and receiving
Follow the above practice and write an endless loop to continuously send and receive data. Use [EXIT!] End the loop.
Establish Servr first:
//The server receives data in an endless loop public class ServerDemo { public static void main(String[] args) throws IOException { //Create server socket ServerSocket serverSocket = new ServerSocket(10086); //Blocking listening Socket socket = serverSocket.accept(); //Receive data circularly byte[] buf = new byte[1024]; int len; System.out.println("Server ready"); while (true) {//Use while to receive len = socket.getInputStream().read(buf); String msg = new String(buf, 0, len); System.out.println("msg = " + msg);//Display the received data if ("EXIT!".equals(msg)) {//Encounter EXIT! End of dead cycle break; } } socket.close(); serverSocket.close(); System.out.println("Server shutdown"); } }
To create a Client again:
//The server receives data in an endless loop public class ServerDemo { public static void main(String[] args) throws IOException { //Create server socket ServerSocket serverSocket = new ServerSocket(10086); //Blocking listening Socket socket = serverSocket.accept(); //Receive data circularly byte[] buf = new byte[1024]; int len; System.out.println("Server ready"); while (true) {//Use while to receive len = socket.getInputStream().read(buf); String msg = new String(buf, 0, len); System.out.println("msg = " + msg);//Display the received data if ("EXIT!".equals(msg)) {//Encounter EXIT! End dead cycle break; } } socket.close(); serverSocket.close(); System.out.println("Server shutdown"); } }
After execution in the correct order, the Client effect:
Enter what to send ha-ha Enter what to send checkssss Enter what to send EXIT! Client shutdown Process finished with exit code 0
Server effect:
Server ready msg = ha-ha msg = checkssss msg = EXIT! Server shutdown Process finished with exit code 0
Transmission and writing
In order to save the data, you can upgrade the above code with the help of IO stream. In order to save characters, UTF-8 encoded character stream is used (the byte stream may report an error when saving Chinese).
Set up the Server first:
//The server circularly receives data and writes it into a file public class ServerDemo { public static void main(String[] args) throws IOException { //Create server socket ServerSocket serverSocket = new ServerSocket(10086); //Blocking listening Socket socket = serverSocket.accept(); //Receive data circularly byte[] buf = new byte[1024]; BufferedWriter bw = new BufferedWriter(new FileWriter("a.txt"));//Efficient byte stream System.out.println("Server on"); while (true) {//Use while to receive int len = socket.getInputStream().read(buf);//Chain programming, read the data of the input stream to the cache array String msg = new String(buf, 0, len);//Converts the data of the buffer array to a string object System.out.println("msg = " + msg); bw.write(msg); bw.newLine();//bufferedwriter does not automatically wrap lines and needs to wrap lines manually bw.flush();//Update file if ("EXIT!".equals(msg)) {//Received EXIT! End dead cycle break; } } //Release resources bw.close();//Put it outside, or you will report an error socket.close(); serverSocket.close(); System.out.println("Server shutdown"); } }
If you put BW close(); An error will be reported if you put it in the while loop:
Exception in thread "main" java.io.IOException: Stream closed at java.io.BufferedWriter.ensureOpen(BufferedWriter.java:116) at java.io.BufferedWriter.write(BufferedWriter.java:221) at java.io.Writer.write(Writer.java:157) at com.at.d20210409.Demo6.ServerDemo.main(ServerDemo.java:31) Process finished with exit code 1
To create a Client again:
//Client input loop public class ClientDemo { public static void main(String[] args) throws IOException { //Create client socket Socket socket = new Socket("127.0.0.1", 10086); //Cyclic output data //Create keyboard entry and receive the information entered by the user Scanner sc = new Scanner(System.in); while (true) { System.out.println("Enter what to send"); String msg = sc.nextLine(); socket.getOutputStream().write(msg.getBytes());//Output the data to the pipeline through the pipeline output stream if ("EXIT!".equals(msg)) {//Send EXIT! End the loop at break; } } //Release resources socket.close(); } }
After execution in the correct order, the Client effect:
Enter what to send ha-ha Enter what to send jjjj Enter what to send EXIT! Process finished with exit code 0
Server effect:
Server on msg = ha-ha msg = jjjj msg = EXIT! Server shutdown Process finished with exit code 0
[a.txt] content:
ha-ha jjjj EXIT!
It can be seen that the required functions have been successfully realized.
Reading, sending and storing documents
Text transmission can be realized by using character stream to read txt file instead of keyboard input in the above case.
Set up the Server first:
//TCP receives data and writes it to b.txt public class ServerDemo { public static void main(String[] args) throws IOException { //Create server socket ServerSocket serverSocket = new ServerSocket(10086); //Blocking listening Socket socket = serverSocket.accept(); System.out.println("Server ready"); //Read data InputStream in = socket.getInputStream(); BufferedWriter bw = new BufferedWriter(new FileWriter("b.txt")); byte[] buf = new byte[1024]; int len; while ((len = in.read(buf)) != -1) {//Write data out to file / /!!! in. The buf parameter must be passed in the read(), otherwise b.txt is empty bw.write(new String(buf, 0, len)); bw.newLine();//Incorrect line feed bw.flush(); } //Release resources bw.close(); socket.close(); serverSocket.close(); System.out.println("Server shutdown"); } }
To create a Client again:
//TCP reads the file and sends it public class ClientDemo { public static void main(String[] args) throws IOException { //Create client socket Socket socket = new Socket("127.0.0.1", 10086); //Create an efficient character input stream to read the contents of the file BufferedReader br = new BufferedReader(new FileReader("a.txt")); String line; while ((line = br.readLine()) != null) { socket.getOutputStream().write(line.getBytes());//Get the pipeline output stream and write the obtained data to the pipeline //After the socket is closed, the getOutputStream stream will be automatically closed, regardless of getOutputStream } //Get the pipeline output stream and write the obtained information to the pipeline //Release resources br.close(); socket.close(); System.out.println("Client shutdown"); } }
First, manually write in [a.txt]:
shifhifhs hfesifhosf fhsihow fshf8hwohw wfjowof sfisf shfoshfo sfiofsof fsifhso EXIT!
Then execute the Server and Client successively. After a certain execution, the content of [b.txt] is as follows:
shifhifhs hfesifhosffhsihowfshf8hwohwwfjowofsfisf shfoshfosfiofsof fsifhso EXIT!
The same amount of data was found, but there was a line feed error. After many tests, it is found that the contents of [b.txt] are different. Don't panic...
Symbol end
Minor changes:
//Read the client data and write it to b.txt. The amount of data is the same, and the line feed is incorrect public class ServerDemo { public static void main(String[] args) throws IOException { //Create server socket ServerSocket serverSocket = new ServerSocket(10086); //Blocking listening Socket socket = serverSocket.accept(); //Read data InputStream in = socket.getInputStream(); BufferedWriter bw = new BufferedWriter(new FileWriter("b.txt")); byte[] buf = new byte[1024]; int len; while ((len = in.read(buf)) != -1){//Write data out to file bw.write(new String(buf,0,len)); bw.newLine(); bw.flush(); } //Feedback to client socket.getOutputStream().write("The server received the end tag".getBytes()); //Release resources bw.close(); socket.close(); serverSocket.close(); } }
Minor changes:
public class ClientDemo { public static void main(String[] args) throws IOException { //Create client socket Socket socket = new Socket("127.0.0.1", 10086); //Create an efficient character input stream to read the contents of the file BufferedReader br = new BufferedReader(new FileReader("a.txt")); String line; while ((line = br.readLine()) != null) {//Get the pipeline output stream and write the obtained information to the pipeline socket.getOutputStream().write(line.getBytes());//After the socket is closed, the getOutputStream stream will be closed automatically } //Write the end symbol so that the input stream of the server can read - 1 socket.shutdownOutput(); byte[] buf = new byte[1024]; int len = socket.getInputStream().read(buf); System.out.println(new String(buf,0,len)); //Release resources br.close(); socket.close(); } }
It is the same [a.txt]. After the correct sequence is executed, the Server effect is as follows:
Process finished with exit code 0
Client effect:
The server received the end tag Process finished with exit code 0
[b.txt] content:
shifhifhs hfesifhosffhsihowfshf8hwohwwfjowofsfisfshfoshfosfiofsof fsifhso EXIT!
Although the connection was successfully disconnected, the written text also wrapped incorrectly... We have to find a way to solve...
Automatic naming and correct line wrapping
File names cannot all be specified manually. Java provides UUID The randomuuid() method generates a random serialized string.
public class UUID_Demo { public static void main(String[] args) { System.out.println("UUID.randomUUID() = " + UUID.randomUUID());//Randomly generated unique identifier new Thread((() -> { for (int i = 0; i < 10; i++) { System.out.println(Thread.currentThread().getName() + i+"UUID.randomUUID() = " + UUID.randomUUID()); } }), "UUID.randomUUID()thread ").start(); } }
After operation:
UUID.randomUUID() = c8b9e792-d179-4992-b86f-ccfd03390bf6 UUID.randomUUID()Thread 0 UUID.randomUUID() = 8ac020c3-6697-44ec-803a-f3293f3e6108 UUID.randomUUID()Thread 1 UUID.randomUUID() = 57b259dc-d24b-4ca7-b5b9-423d3f3aca3d UUID.randomUUID()Thread 2 UUID.randomUUID() = 0d886854-a874-4054-97ec-afcdf4d29ab1 UUID.randomUUID()Thread 3 UUID.randomUUID() = df3e9a4c-4bc0-4da2-b9c6-cf2b42568eb8 UUID.randomUUID()Thread 4 UUID.randomUUID() = f8c5ceeb-c9cd-44e6-be24-242d2651dea3 UUID.randomUUID()Thread 5 UUID.randomUUID() = bd694173-104c-4f89-81a0-b1fc48e3e7e9 UUID.randomUUID()Thread 6 UUID.randomUUID() = 5a0b101b-dfca-40ea-8bbe-f3fa51e32532 UUID.randomUUID()Thread 7 UUID.randomUUID() = e4d07189-272c-41e7-9ae2-27703f0c0743 UUID.randomUUID()Thread 8 UUID.randomUUID() = ae00f03a-2427-4b39-9899-c93d39313548 UUID.randomUUID()Thread 9 UUID.randomUUID() = 8479b778-e655-4eeb-a72e-122dce3a64a9 Process finished with exit code 0
Obviously, you can use UUID The random () method gets the folder name.
The read / write IO is optimized by multithreading, so multiple read / write operations can be performed at the same time.
The Client manually adds the line feed symbol ["\ n\t"] to solve the problem of incorrect line feed.
After optimization, the Client can write:
//Multithreaded TCP client public class ClientDemo { public static void main(String[] args) throws IOException { //Create client socket Socket socket = new Socket("127.0.0.1", 10086); //Create an efficient character input stream to read the contents of the file BufferedReader br = new BufferedReader(new FileReader("a.txt"));//Efficient stream does not read line breaks, and ordinary character stream is more suitable String line; while ((line = br.readLine()) !=null){//Get the pipeline output stream and write the obtained information to the pipeline socket.getOutputStream().write((line+"\r\n").getBytes());//After the socket is closed, the getOutputStream stream will be closed automatically //Write line feed directly in the output stream to solve the problem of incorrect line feed at the server } //Write the end symbol so that the input stream of the server can read - 1 socket.shutdownOutput(); byte[] buf = new byte[1024]; int len = socket.getInputStream().read(buf); System.out.println(new String(buf,0,len)); //Release resources br.close(); socket.close(); } }
Custom thread implementation class:
public class ThreadIO extends Thread { private Socket socket; public ThreadIO(Socket socket) { this.socket = socket; } @Override public void run() { //Read data try { InputStream in = socket.getInputStream(); BufferedWriter bw = new BufferedWriter(new FileWriter("1.txt")); byte[] buf = new byte[1024]; int len; while ((len = in.read(buf)) != -1) {//Write out input to file bw.write(new String(buf,0,len)); bw.newLine(); bw.flush();//Refresh } //Feed data back to the server socket.getOutputStream().write("Server received data".getBytes()); //Release resources bw.close(); socket.close(); } catch (IOException e) { e.printStackTrace(); } } }
Multithreaded TCPServer can use two methods:
//Multithreaded TCP server public class ServerDemo { public static void main(String[] args) throws IOException { ServerSocket serverSocket = new ServerSocket(10086); while (true) { Socket socket = serverSocket.accept();//The dead loop will not create a new socket without brains. It will block listening. It will only create a new socket when there is a connection Method1(socket);//Anonymous inner class method Method2(socket);//Custom threading mode } } public static void Method1(Socket socket) { //IO operation is time-consuming. In order to avoid taking a lot of time, throw the time-consuming operation to the thread and start the thread //Anonymous inner class new Thread() { @Override public void run() { //read try { InputStream in = socket.getInputStream(); BufferedWriter bw = new BufferedWriter(new FileWriter(UUID.randomUUID() + ".txt"));//Generate randomly to avoid different client s overwriting the previous files byte[] buf = new byte[1024]; int len ; //write while ((len = in.read(buf)) !=-1){ bw.write(new String(buf,0,buf.length)); bw.newLine(); bw.flush(); } System.out.println("A thread has finished reading"); socket.getOutputStream().write("A thread has finished reading".getBytes()); bw.close(); socket.close(); //serverSocket.close();// Closing ServerSocket will result in an error } catch (IOException e) { e.printStackTrace(); } } }.start(); System.out.println("Enable multithreading of anonymous inner classes"); } public static void Method2(Socket socket) { new ThreadIO(socket).run(); System.out.println("Enable multithreading of custom thread class"); } }
The author extracts them as Method1 and Method2. Both methods can be used, but only one method can be used at the same time (because the two methods share a serverSocket socket, using the two methods at the same time will occupy the server socket).
Using Method1, after starting the Server and Client respectively, a [C: \ users \ killer \ ideaprojects \ test1 \ fbcc52b-89a5-4778-9225-b01c0725c704. TXT] is generated. The Server:
Enable multithreading of anonymous inner classes A thread has finished reading
(the server needs to end manually)
client:
A thread has finished reading Process finished with exit code 0
[fbccc52b-89a5-4778-9225-b01c0725c704.txt] content:
shifhifhs hfesifhosf fhsihow fshf8hwohw wfjowof sfisf shfoshfo sfiofsof fsifhso EXIT!
Line feed succeeded!!!
Try Method2 again, and a [1.txt] is generated, which reads:
shifhifhs hfesifhosf fhsihow fshf8hwohw wfjowof sfisf shfoshfo sfiofsof fsifhso EXIT!
Similarly, the line feed is successful!!!
Byte stream reads and writes files and transfers them
Set up Server:
public class ServerDemo { public static void main(String[] args) throws IOException { //Create server socket ServerSocket serverSocket = new ServerSocket(10086); //Use dead loop, loop monitoring while (true) { Socket socket = serverSocket.accept(); //How to implement the interface new Thread(new Runnable() {//Put IO time-consuming operations into thread operations @Override public void run() {//ctrl+art+t try { InputStream is = socket.getInputStream(); FileOutputStream fos = new FileOutputStream("b.avi"); //Gets the pipeline input stream and reads data from the pipeline byte[] buf = new byte[1024 * 8]; int len; while ((len = is.read(buf)) != -1) {//Write the read data to the file fos.write(buf, 0, len); fos.flush();//Refresh to ensure data update } //Receive information to the client socket.getOutputStream().write("Read complete".getBytes()); //Release resources fos.close();//Release occupation socket.close(); } catch (Exception e) { e.printStackTrace(); } } }).start(); } } }
Create Client:
public class ClientDemo { public static void main(String[] args) throws IOException { //Create client socket Socket socket = new Socket("127.0.0.1", 10086); //Create byte input stream read file FileInputStream fis = new FileInputStream("a.avi"); byte[] buf = new byte[1024*8]; int len; while ((len = fis.read(buf))!=-1){ socket.getOutputStream().write(buf,0,len);//Write data to pipeline } //Write end symbol to pipe socket.shutdownOutput(); //Receiving server receipt len = socket.getInputStream().read(buf); System.out.println(new String(buf,0,len)); //Release resources fis.close(); socket.close(); } }
After execution:
The C disk is a 300M/s SSD disk, and there is basically no difference in byte size... All completed within 2s...