Socket communication based on TCP protocol (1) Classification Android basic introductory tutorial


Introduction to this section:

The concept lesson in the previous section was boring, right, but there is always something to gain, right? At the beginning of this section we will study Socket based on the TCP protocol For communication, let’s first understand the concept of Socket, the model of Socket communication, the steps to implement Socket, and as a Socket service The client and the client each have to do what they want to do! Okay, let's debug this Socket from the shallower to the deeper!


What is Socket?

1.png


2.Socket communication model:

2.png

Socket communication implementation steps analysis :

Step 1: Create ServerSocket and Socket

Step 2: Open the input/output of the Socket connected to Stream


Step 3: Read/write the Socket according to the protocol

Step 4: Close Input and output streams, and Socket

Okay, let's write a simple example next. After opening the server, the client clicks the button and then connects to the server. And send a string of strings to the server, indicating that the server is connected through Socket~


3. Writing the Socket server:

The things the server needs to do are these :

Step 1: Create a ServerSocket object and bind the listening port

Step 2: Call accept() Method to monitor the client's request

Step 3: After the connection is established, read the request information sent by the client through the input stream

Step 4: Send response information to the client through the output stream

Step 5: Close related resources

Code implementation:

Create a Java project directly under Eclipse and paste the Java code into it!

public class SocketServer {
	public static void main(String[] args) throws IOException {
		//1.创建一个服务器端Socket,即ServerSocket,指定绑定的端口,并监听此端口
		ServerSocket serverSocket = new ServerSocket(12345);
		InetAddress address = InetAddress.getLocalHost();
		String ip = address.getHostAddress();
		Socket socket = null;
		//2.调用accept()等待客户端连接
		System.out.println("~~~服务端已就绪,等待客户端接入~,服务端ip地址: " + ip);
		socket = serverSocket.accept();
		//3.连接后获取输入流,读取客户端信息
		InputStream is=null;
		InputStreamReader isr=null;
		BufferedReader br=null;
		OutputStream os=null;
		PrintWriter pw=null;
		is = socket.getInputStream();     //获取输入流
		isr = new InputStreamReader(is,"UTF-8");
		br = new BufferedReader(isr);
		String info = null;
		while((info=br.readLine())!=null){//循环读取客户端的信息
			System.out.println("客户端发送过来的信息" + info);
		}
		socket.shutdownInput();//关闭输入流
		socket.close();
	}
}

Then we run the code, and the console will print:

3.png

Okay, now comes the Android client!


4. Writing the Socket client:

The client has to do these things:

Step 1: Create a Socket object and specify the address and port number of the server to be connected

Step 2: After the link is established, send the request information to the server through the output stream

Step 3: Obtain the server response information through the output stream

Step 4: Close related resources

Code implementation

MainActivity.java

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button btn_accept = (Button) findViewById(R.id.btn_accept);
        btn_accept.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        new Thread() {
            @Override
            public void run() {
                try {
                    acceptServer();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }.start();
    }

    private void acceptServer() throws IOException {
        //1.创建客户端Socket,指定服务器地址和端口
        Socket socket = new Socket("172.16.2.54", 12345);
        //2.获取输出流,向服务器端发送信息
        OutputStream os = socket.getOutputStream();//字节输出流
        PrintWriter pw = new PrintWriter(os);//将输出流包装为打印流
        //获取客户端的IP地址
        InetAddress address = InetAddress.getLocalHost();
        String ip = address.getHostAddress();
        pw.write("客户端:~" + ip + "~ 接入服务器!!");
        pw.flush();
        socket.shutdownOutput();//关闭输出流
        socket.close();
    }
}

Because Android does not allow network operations in the main thread (UI thread), we need to do this ourselves Open another thread to connect to the Socket!

Run result:

After clicking the button, the server console prints:

4.png

5. Enhanced version case: Xiaozhu Simple Chat Room

Just click a button, and then the server returns a string of information. It must be very boring, right? Come down and let's do it To build a super simple chat room, we need to use a thread pool to store a collection of Socket links. We also need Write a thread by byte, let’s experience the details in the code!

Rendering of the implementation:

First run our server:

5.png

Then separate our programs Run to two simulators:

6.gif

Next let’s write the code:

The first is the server, which is to put the operations of reading and writing sockets into custom threads and create After ServerSocket, loop Call the accept method. When a new client accesses, add the socket to the collection and create a new thread in the thread pool!

In addition, in the method of reading information, the input string is judged. If it is a bye string, the socket is removed from the collection. Remove and close it!

Server.java:

public class Server {
	//定义相关的参数,端口,存储Socket连接的集合,ServerSocket对象
	//以及线程池
	private static final int PORT = 12345;
	private List mList = new ArrayList();
	private ServerSocket server = null;
	private ExecutorService myExecutorService = null;
	
	
	public static void main(String[] args) {
		new Server();
	}

	public Server()
	{
		try
		{
			server = new ServerSocket(PORT);
			//创建线程池
			myExecutorService = Executors.newCachedThreadPool();
			System.out.println("服务端运行中...\n");
			Socket client = null;
			while(true)
			{
				client = server.accept();
				mList.add(client);
				myExecutorService.execute(new Service(client));
			}
			
		}catch(Exception e){e.printStackTrace();}
	}
	
	class Service implements Runnable
	{
		private Socket socket;
		private BufferedReader in = null;
		private String msg = "";
		
		public Service(Socket socket) {
			this.socket = socket;
			try
			{
				in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
				 msg = "用户:" +this.socket.getInetAddress() + "~加入了聊天室"  
	                        +"当前在线人数:" +mList.size();  
				this.sendmsg();
			}catch(IOException e){e.printStackTrace();}
		}
		
		
		
		@Override
		public void run() {
			try{
				while(true)
				{
					if((msg = in.readLine()) != null)
					{
						if(msg.equals("bye"))
						{
							System.out.println("~~~~~~~~~~~~~");
							mList.remove(socket);
                            in.close();
                            msg = "用户:" + socket.getInetAddress()  
                                    + "退出:" +"当前在线人数:"+mList.size();  
                            socket.close();  
                            this.sendmsg();  
                            break;
						}else{
							msg = socket.getInetAddress() + "   说: " + msg;  
                            this.sendmsg(); 
						}
					}
				}
			}catch(Exception e){e.printStackTrace();}
		}
		
		//为连接上服务端的每个客户端发送信息
		public void sendmsg()
		{
			System.out.println(msg);
			int num = mList.size();
			for(int index = 0;index < num;index++)
			{
				Socket mSocket = mList.get(index);  
                PrintWriter pout = null;  
                try {  
                    pout = new PrintWriter(new BufferedWriter(  
                            new OutputStreamWriter(mSocket.getOutputStream(),"UTF-8")),true);  
                    pout.println(msg);  
                }catch (IOException e) {e.printStackTrace();}  
			}
		}
		
	}
}

Then to the client, the difficulty of the client is to open another thread, because Android does not allow directly Do network operations in the main thread, and do not allow threads outside the main thread to operate the UI. The approach here is to create a new one yourself. A thread, and updating the UI through Hanlder. In actual development, it is not recommended to do this directly! ! !

Layout file:activity_main.xml

                

MainActivity.java:

public class MainActivity extends AppCompatActivity implements Runnable {

    //定义相关变量,完成初始化
    private TextView txtshow;
    private EditText editsend;
    private Button btnsend;
    private static final String HOST = "172.16.2.54";
    private static final int PORT = 12345;
    private Socket socket = null;
    private BufferedReader in = null;
    private PrintWriter out = null;
    private String content = "";
    private StringBuilder sb = null;

    //定义一个handler对象,用来刷新界面
    public Handler handler = new Handler() {
        public void handleMessage(Message msg) {
            if (msg.what == 0x123) {
                sb.append(content);
                txtshow.setText(sb.toString());
            }
        }

        ;
    };


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        sb = new StringBuilder();
        txtshow = (TextView) findViewById(R.id.txtshow);
        editsend = (EditText) findViewById(R.id.editsend);
        btnsend = (Button) findViewById(R.id.btnsend);

        //当程序一开始运行的时候就实例化Socket对象,与服务端进行连接,获取输入输出流
        //因为4.0以后不能再主线程中进行网络操作,所以需要另外开辟一个线程
        new Thread() {

            public void run() {
                try {
                    socket = new Socket(HOST, PORT);
                    in = new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF-8"));
                    out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(
                            socket.getOutputStream())), true);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }.start();

        //为发送按钮设置点击事件
        btnsend.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                String msg = editsend.getText().toString();
                if (socket.isConnected()) {
                    if (!socket.isOutputShutdown()) {
                        out.println(msg);
                    }
                }
            }
        });
        new Thread(MainActivity.this).start();
    }

    //重写run方法,在该方法中输入流的读取
    @Override
    public void run() {
        try {
            while (true) {
                if (socket.isConnected()) {
                    if (!socket.isInputShutdown()) {
                        if ((content = in.readLine()) != null) {
                            content += "\n";
                            handler.sendEmptyMessage(0x123);
                        }
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Summary of this section:

Okay, this section explains Socket communication based on TCP. The article introduces the Socket communication model and implements A simple Socket communication example, and an enhanced version of it: Piggy Chat Room, I believe it will be useful to those who are just involved Socket programming brings you convenience~, thank you~