1.1 software structure
-
C/S structure: the full name is Client/Server structure, which refers to client and server structure. Common programs include QQ, Xunlei and other software.
-
B/S structure: fully known as Browser/Server structure, it refers to browser and server structure. Common browsers include Google, Firefox, etc.
The two architectures have their own advantages, but no matter which architecture, it is inseparable from the support of the network. Network programming is a program that realizes the communication between two computers under a certain protocol.
1.2 network communication protocol
-
**Network communication protocol: * * multiple computers can be connected through the computer network. Computers located in the same network need to abide by certain rules when connecting and communicating, just as cars driving on the road must abide by traffic rules. In the computer network, these connection and communication rules are called network communication protocol. It makes unified provisions on the data transmission format, transmission rate and transmission steps. Both sides of the communication must abide by them at the same time to complete the data exchange.
-
TCP/IP protocol: Transmission Control Protocol / Internet protocol, which is the most basic and extensive protocol on the Internet. It defines standards for how computers connect to the Internet and how data is transmitted between them. It contains a series of protocols for processing data communication, and adopts a 4-layer layered model. Each layer calls the protocols provided by its next layer to complete its own requirements.
In the figure above, the four layers of TCP/IP protocol are application layer, transmission layer, network layer and link layer, and each layer is responsible for different communication functions. -
Link layer: the link layer is used to define the physical transmission channel. It is usually the driving protocol for some network connection devices, such as the driver provided for optical fiber and network cable.
-
Network layer: the network layer is the core of the whole TCP/IP protocol. It is mainly used to group the transmitted data and send the packet data to the target computer or network.
-
Transport layer: it mainly enables network programs to communicate. TCP protocol or UDP protocol can be used for network communication.
-
Application layer: mainly responsible for the application protocol, such as HTTP protocol, FTP protocol, etc.
1.3 protocol classification
The communication protocol is still relatively complex. The classes and interfaces contained in the java.net package provide bottom-level communication details. We can directly use these classes and interfaces to focus on network program development without considering the details of communication.
The java.net package provides support for two common network protocols:
- UDP: user datagram protocol. UDP is a connectionless communication protocol, that is, during data transmission, the sender and receiver of data do not establish a logical connection. In short, when a computer sends data to another computer, the sender will send data without confirming whether the receiver exists. Similarly, when the receiver receives data, it will not feed back whether it has received data to the sender. Because UDP protocol consumes less resources and has high communication efficiency, it is usually used for the transmission of audio, video and ordinary data. For example, video conference uses UDP protocol, because even if one or two packets are lost occasionally, it will not have a great impact on the receiving results.
Features: the data is limited to 64kb, beyond which it cannot be sent.
Datagram: the basic unit of network transmission
TCP: transmission control protocol. TCP protocol is a connection oriented communication protocol, that is, before transmitting data, establish a logical connection between the sender and the receiver, and then transmit data. It provides reliable error free data transmission between two computers.
In TCP connection, the client and server must be specified. The client sends a connection request to the server. Each connection creation needs to go through "three handshakes".
Three handshakes: in TCP protocol, three interactions between the client and the server in the preparation stage of sending data to ensure the reliability of the connection.
- The first handshake, the client sends a connection request to the server and waits for the server to confirm.
- In the second handshake, the server sends back a response to the client to notify the client that it has received the connection request.
- For the third handshake, the client sends a confirmation message to the server again to confirm the connection. The whole interaction process is shown in the figure below.
After three handshakes are completed and the connection is established, the client and server can start data transmission. Because of this connection oriented feature, TCP protocol can ensure the security of data transmission, so it is widely used, such as downloading files, browsing web pages and so on.
1.4 three elements of network programming
agreement
- Protocol: the rules that must be observed in computer network communication
IP address
- IP address: refers to the Internet Protocol Address, commonly known as IP. IP addresses are used to uniquely number computer devices in a network. If we compare "personal computer" to "a telephone", then "IP address" is equivalent to "telephone number".
IP address classification
-
IPv4: it is a 32-bit binary number, which is usually divided into 4 bytes and expressed in the form of a.b.c.d, such as 192.168.65.100. Where a, B, C and D are decimal integers between 0 and 255, it can represent 4.2 billion at most.
-
IPv6: due to the vigorous development of the Internet, the demand for IP address is increasing, but the limited network address resources make the allocation of IP more and more tense.
In order to expand the address space, it is proposed to redefine the address space through IPv6. The 128 bit address length is adopted, a group of 16 bytes is divided into 8 groups of hexadecimal numbers, expressed as ABCD:EF01:2345:6789:ABCD:EF01:2345:6789. It is said that it can compile a network address for every grain of sand in the world, which solves the problem of insufficient network address resources.
Common commands
- To view the local IP address, enter:
ipconfig
- Check whether the network is connected. Enter:
ping Space IP address ping 220.181.57.216
Special IP address
- Local IP address: 127.0.0.1, localhost.
Port number
Network communication is essentially the communication between two processes (Applications). Each computer has many processes, so how to distinguish these processes in network communication?
If the IP address can uniquely identify the device in the network, the port number can uniquely identify the process (application) in the device.
- **Port number: an integer represented by two bytes. Its value range is 065535 * *. Among them, the port numbers between 01023 are used for some well-known network services and applications, and ordinary applications need to use port numbers above 1024. If the port number is occupied by another service or application, the current program will fail to start.
Using the ternary combination of protocol + IP address + port number, the processes in the network can be identified, and the communication between processes can use this identification to interact with other processes.
TCP communication program
2.1 general
TCP communication can realize the data interaction between two computers. The two ends of communication should be strictly divided into Client and Server.
Steps for communication between two ends:
- The server program needs to be started in advance and wait for the connection of the client.
- The client actively connects to the server and can communicate only after the connection is successful. The server cannot actively connect to the client.
In Java, two classes are provided to implement TCP communication programs:
- Client: represented by java.net.Socket class. Create a Socket object, send a connection request to the server, and the server responds to the request. The two establish a connection and start communication.
- Server: represented by java.net.ServerSocket class. Creating a ServerSocket object is equivalent to starting a service and waiting for the client to connect.
2.2 Socket class
Socket class: this class implements client socket. Socket refers to the endpoint of communication between two devices.
Construction method
-
public Socket(String host, int port): creates a socket object and connects it to the specified port number on the specified host. If the specified host is null, it is equivalent to that the specified address is the loopback address.
Tip: the Loopback Address (127.x.x.x) is the Loopback Address of the local machine. It is mainly used for network software testing and local machine interprocess communication. No matter what program uses the Loopback Address to send data, it will return immediately without any network transmission.
For example, the code is as follows:
Socket client = new Socket("127.0.0.1", 6666);
Member method
-
public InputStream getInputStream(): returns the input stream of this socket.
- If this socket has an associated channel, all operations of the generated InputStream are also associated with that channel.
- Closing the generated InputStream will also close the relevant Socket.
-
public OutputStream getOutputStream(): returns the output stream of this socket.
- If this socket has an associated channel, all operations of the generated OutputStream are also associated with the channel.
- Closing the generated OutputStream will also close the relevant Socket.
-
public void close(): close this socket.
- Once a socket is closed, it can no longer be used.
- Closing this socket will also close the associated InputStream and OutputStream.
-
public void shutdownOutput(): disables the output stream of this socket.
- Any previously written data will be sent, and then the output stream will be terminated.
2.3 ServerSocket class
ServerSocket class: this class implements the server socket, which waits for requests through the network.
Construction method
- public ServerSocket(int port): when creating a ServerSocket object using this construction method, you can bind it to a specified port number. The parameter port is the port number.
For example, the code is as follows:
ServerSocket server = new ServerSocket(6666);
Member method
- public Socket accept(): listen and accept the connection, and return a new Socket object for communication with the client. This method blocks until a connection is established.
2.4 simple TCP network program
TCP communication analysis diagram
- Start the server, create a ServerSocket object, and wait for the connection.
- [Client] start, create Socket object and request connection.
- [server] receives the connection, calls the accept method, and returns a Socket object.
- [Client] Socket object, obtain OutputStream and write data to the server.
- [server] socket object, get InputStream and read the data sent by the client.
At this point, the client successfully sends data to the server.
Since then, the server writes back data to the client.
- [server] Socket object, obtain OutputStream and write back data to the client.
- [Client] socket object, get InputStream, parse and write back data.
- [Client] release resources and disconnect.
The client sends data to the server
Server implementation:
/** TCP Protocol server: ServerSocket Socket accept() Client listening for links */ public class NewTcpServer { public static List<MyChannel> all; //Create a collection ArrayList; Used to store received customer objects public static void main(String[] args) throws IOException { //Instantiate the server ServerSocket and listen for the specified port number ServerSocket server = new ServerSocket(9999); all = new ArrayList<>(); int count=0; while (true){ //The server can listen to who the connected client is;; Socket accept() method; Socket client = server.accept(); System.out.println("One socket connect..."); //Receive data from the client / send information to the client count++; MyChannel channel = new MyChannel(count,client,all); new Thread(channel).start(); all.add(channel); } } }
Server thread program class
public class MyChannel implements Runnable { //Socket for receiving clients private Socket accept; //The server reads the client data stream DataInputStream private DataInputStream dis; //console output private BufferedReader console; //The server outputs data to the client private DataOutputStream dos; //Executable ID private boolean isRunning = true; private int id; private List<MyChannel> all; public MyChannel(int count, Socket accept, List<MyChannel> all) { id = count; this.all = all; this.accept = accept; try { //The server reads client messages dis = new DataInputStream(accept.getInputStream()); dos = new DataOutputStream(accept.getOutputStream()); //Console write message console = new BufferedReader(new InputStreamReader(System.in)); } catch (IOException e) { IOUtilss.closeAll(dis, dos, accept, console); isRunning = false; } } @Override public void run() { //Receive data from client Receive() method while (isRunning) { String msg = receive(); if (msg.contains("@")){ // Chat(msg); }else { allChat(msg); } System.out.println(msg); // String sfc = getStrFromConsole(); } } private void Chat(String msg) { String s = msg.replace("@", ""); } private void allChat(String msg) { for (MyChannel myChannel : all) { if (myChannel == this) { } else { try { myChannel.dos.writeUTF(msg); } catch (IOException e) { e.printStackTrace(); } } } } //The server receives client messages public String receive() { String data = ""; try { String s = dis.readUTF(); if (!s.equals("")) { data = s; } } catch (IOException e) { IOUtilss.closeAll(dis); isRunning = false; } return data; } //Read out information from the console public String getStrFromConsole() { try { String s = console.readLine(); if (!s.equals("")) { return s; } } catch (IOException e) { e.printStackTrace(); } return ""; } //The server sends a message to the client public void send(String msg) { try { dos.writeUTF(msg); dos.flush(); } catch (IOException e) { isRunning = false; //IOUtilss.closeAll(dos); } } }
Client implementation:
public class NewTcpClient { public static void main(String[] args) throws IOException { System.out.println("=====client===="); //New basket //1. Specify ip + port number; Establish connection Socket socket = new Socket("127.0.0.1",9999); //2. Create two threads: ensure that the client sends & & receives messages without interference with each other //A class object Send(socket) for sending messages; Construction method with one parameter; Used to establish a connection by passing parameters //A class object Receive(socket) that receives messages; Construction method with one parameter; Used to establish a connection by passing parameters new Thread( new Send(socket)).start(); new Thread(new Receive(socket)).start(); } }
Send thread implementation class
//Client send task //1. Create customer connections // 2. dataoutputStream stream of messages sent by customers // 3. Get the BufferReader stream of the message from the keyboard //In the run method: get the console message getStrFormConsole() and send the message send() public class Send implements Runnable{ //Socket for receiving clients private Socket client; //Client connection private DataOutputStream dos; //The client sends information; dataOutputStream stream implementation private BufferedReader console; //The console receives keyboard information; BufferedReader implementation //Executable tag private boolean isRunning = true; public Send(Socket client) { this.client = client; try { //With the help of conversion flow, data is entered in the console console = new BufferedReader(new InputStreamReader(System.in)); dos = new DataOutputStream(client.getOutputStream()); } catch (IOException e) { //If an exception occurs, the client will send a message and the flow will be closed IOUtilss.closeAll(console,client,dos); isRunning=false; } } @Override public void run() { while (isRunning){ //Get keyboard input data //Send a method to get data String strFormConsole = getStrFormConsole(); //Judgment (if the data is not empty, output the data;) if(!strFormConsole.equals("")){ send(strFormConsole); } } } //Get message from console private String getStrFormConsole(){ try { return console.readLine(); } catch (IOException e) { e.printStackTrace(); } return ""; } //Send the obtained message to the server public void send(String msg){ try { dos.writeUTF(msg); dos.flush(); } catch (IOException e) { e.printStackTrace(); isRunning = false; } } }
Client receiving class implementation;
/** * Client receiving task * 1,Establish Socket connection; * 2,Create a DataInputStream that reads in server data * 3,Design a representation to judge whether reading data stops * 4,run Method to receive data from the server */ public class Receive implements Runnable{ private Socket client; private DataInputStream dis; private boolean isRunning = true; public Receive(Socket client) { this.client = client; try { //Create an input stream to connect to the client dis = new DataInputStream(client.getInputStream()); } catch (IOException e) { //If an exception occurs, close the flow and end the thread IOUtilss.closeAll(dis); isRunning = false; } } @Override public void run() { while (isRunning){ //Receive messages from the server String msg = receive(); //Judgment: if the message from the server is not empty, output the message if(!msg.equals("")){ System.out.println(msg); } } } //The client reads data from the server public String receive(){ String msg = ""; try { msg = dis.readUTF(); } catch (IOException e) { IOUtilss.closeAll(dis,client); isRunning = false; } return msg; } }
Comprehensive case
3.1 file upload cases
- [Client] input stream to read file data from hard disk into program.
- [Client] output the stream and write out the file data to the server.
- [server] input the stream and read the file data to the server program.
- [server] output stream, write out file data to the server hard disk.
Server implementation:
public class FileUpload_Server { public static void main(String[] args) throws IOException { System.out.println("Server startup..... "); // 1. Create server ServerSocket ServerSocket serverSocket = new ServerSocket(6666); // 2. Establish connection Socket accept = serverSocket.accept(); // 3. Create flow object // 3.1 get the input stream and read the file data BufferedInputStream bis = new BufferedInputStream(accept.getInputStream()); // 3.2 create an output stream and save it locally BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("copy.jpg")); // 4. Read and write data byte[] b = new byte[1024 * 8]; int len; while ((len = bis.read(b)) != -1) { bos.write(b, 0, len); } //5. Close resources bos.close(); bis.close(); accept.close(); System.out.println("File upload saved"); } }
Client implementation:
public class FileUPload_Client { public static void main(String[] args) throws IOException { // 1. Create flow object // 1.1 create input stream and read local files BufferedInputStream bis = new BufferedInputStream(new FileInputStream("test.jpg")); // 1.2 create an output stream and write it to the server Socket socket = new Socket("localhost", 6666); BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream()); //2. Write the data byte[] b = new byte[1024 * 8 ]; int len ; while (( len = bis.read(b))!=-1) { bos.write(b, 0, len); bos.flush(); } System.out.println("File sent"); // 3. Release resources bos.close(); socket.close(); bis.close(); System.out.println("File upload completed "); } }
File upload optimization analysis
-
The file name is dead
On the server side, if the name of the saved file is written dead, only one file will be retained on the server hard disk. It is recommended to use system time optimization to ensure that the file name is unique. The code is as follows:
FileOutputStream fis = new FileOutputStream(System.currentTimeMillis()+".jpg") // File name BufferedOutputStream bos = new BufferedOutputStream(fis);
-
Circular reception problem
The server is closed after saving a file, which is not practical. It can continuously receive files from different users by using circular improvement. The code is as follows:
// Each time a new connection is received, a Socket is created while(true){ Socket accept = serverSocket.accept(); ...... }
-
Efficiency issues
The server may take a few seconds to receive large files. At this time, it cannot receive uploads from other users. Therefore, it is optimized using multithreading technology. The code is as follows:
while(true){ Socket accept = serverSocket.accept(); // accept to the child thread new Thread(() -> { ...... InputStream bis = accept.getInputStream(); ...... }).start(); }
Optimized implementation
public class FileUpload_Server { public static void main(String[] args) throws IOException { System.out.println("Server startup..... "); // 1. Create server ServerSocket ServerSocket serverSocket = new ServerSocket(6666); // 2. Receive circularly and establish connection while (true) { Socket accept = serverSocket.accept(); /* 3. socket Object is handed over to the child thread for reading and writing Runnable In the interface, there is only one run method, which uses lambda expressions to simplify the format */ new Thread(() -> { try ( //3.1 get input stream object BufferedInputStream bis = new BufferedInputStream(accept.getInputStream()); //3.2 create an output stream object and save it locally FileOutputStream fis = new FileOutputStream(System.currentTimeMillis() + ".jpg"); BufferedOutputStream bos = new BufferedOutputStream(fis);) { // 3.3 reading and writing data byte[] b = new byte[1024 * 8]; int len; while ((len = bis.read(b)) != -1) { bos.write(b, 0, len); } //4. Close resources bos.close(); bis.close(); accept.close(); System.out.println("File upload saved"); } catch (IOException e) { e.printStackTrace(); } }).start(); } } }
Information write back analysis diagram
The first four steps are consistent with the basic file upload
- [server] obtain the output stream and write back the data.
- [Client] obtain the input stream and parse the write back data.
Writeback implementation
public class FileUpload_Server { public static void main(String[] args) throws IOException { System.out.println("Server startup..... "); // 1. Create server ServerSocket ServerSocket serverSocket = new ServerSocket(6666); // 2. Receive circularly and establish connection while (true) { Socket accept = serverSocket.accept(); /* 3. socket Object is handed over to the child thread for reading and writing Runnable In the interface, there is only one run method, which uses lambda expressions to simplify the format */ new Thread(() -> { try ( //3.1 get input stream object BufferedInputStream bis = new BufferedInputStream(accept.getInputStream()); //3.2 create an output stream object and save it locally FileOutputStream fis = new FileOutputStream(System.currentTimeMillis() + ".jpg"); BufferedOutputStream bos = new BufferedOutputStream(fis); ) { // 3.3 reading and writing data byte[] b = new byte[1024 * 8]; int len; while ((len = bis.read(b)) != -1) { bos.write(b, 0, len); } // 4. ========= information update=========================== System.out.println("back ........"); OutputStream out = accept.getOutputStream(); out.write("Upload succeeded".getBytes()); out.close(); //================================ //5. Close resources bos.close(); bis.close(); accept.close(); System.out.println("File upload saved"); } catch (IOException e) { e.printStackTrace(); } }).start(); } } }
Client implementation:
public class FileUpload_Client { public static void main(String[] args) throws IOException { // 1. Create flow object // 1.1 create input stream and read local files BufferedInputStream bis = new BufferedInputStream(new FileInputStream("test.jpg")); // 1.2 create an output stream and write it to the server Socket socket = new Socket("localhost", 6666); BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream()); //2. Write the data byte[] b = new byte[1024 * 8 ]; int len ; while (( len = bis.read(b))!=-1) { bos.write(b, 0, len); } // Close the output stream and notify the server that the data is written out socket.shutdownOutput(); System.out.println("File sent"); // 3. = = = = parse writeback============ InputStream in = socket.getInputStream(); byte[] back = new byte[20]; in.read(back); System.out.println(new String(back)); in.close(); // ============================ // 4. Release resources socket.close(); bis.close(); } }