Komunikasi soket berdasarkan protokol TCP (1) Klasifikasi tutorial pengenalan asas Android


Pengenalan bahagian ini:

Pelajaran konsep di bahagian sebelumnya memang membosankan, tetapi sentiasa ada sesuatu yang bermanfaat, bukan? protokol TCP Untuk komunikasi, mari kita fahami konsep Socket, model komunikasi Socket, langkah-langkah untuk melaksanakan Socket, dan sebagai perkhidmatan Socket Pelanggan dan pelanggan masing-masing perlu melakukan apa yang mereka mahu lakukan! Okey, mari kita nyahpepijat Soket ini daripada yang cetek kepada yang lebih dalam!


Apakah itu Soket?

1.png


2. Model komunikasi soket:

2.png

Analisis langkah-langkah pelaksanaan komunikasi soket :

Langkah 1: Cipta ServerSocket dan Socket

Langkah 2: Buka input/output Soket yang disambungkan untuk Strim


Langkah 3: Baca/tulis Soket mengikut protokol

Langkah 4: Tutup Strim input dan output, dan Soket

Baiklah, mari tulis contoh mudah seterusnya Selepas memulakan pelayan, pelanggan mengklik butang dan kemudian menyambung ke pelayan. Dan hantar rentetan rentetan ke pelayan, menunjukkan bahawa pelayan disambungkan melalui Soket~


3 Menulis pelayan Soket:

Perkara yang diperlukan oleh pelayan. yang perlu dilakukan ialah ini

Langkah 1: Buat objek ServerSocket dan ikat port mendengar

Langkah 2: Call accept() Kaedah untuk mendengar permintaan pelanggan

Langkah 3: Selepas sambungan diwujudkan, baca maklumat permintaan yang dihantar oleh klien melalui aliran input

Langkah 4: Hantar maklumat respons kepada klien melalui strim output

Langkah 5: Tutup sumber berkaitan

Kod pelaksanaan :

Cipta projek Java terus di bawah Eclipse, dan kemudian tampal kod Java ke dalamnya!

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();
	}
}

Kemudian kami menjalankan kod, dan konsol akan mencetak:

3.png

Baiklah, kini datang pelanggan Android!


4. Penulisan klien Socket:

Pelanggan perlu melakukan perkara ini :

Langkah 1 : Cipta objek Soket dan nyatakan alamat dan nombor port pelayan untuk dipautkan

Langkah 2: Selepas pautan diwujudkan, hantar maklumat permintaan kepada pelayan melalui strim output

Langkah 3: Dapatkan maklumat respons pelayan melalui strim output

Langkah 4: Tutup sumber berkaitan

Pelaksanaan kod

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();
    }
}

Kerana Android tidak membenarkan operasi rangkaian dilakukan dalam utas utama ( benang UI), kita perlu melakukannya sendiri Buka urutan lain untuk menyambung ke Soket!

Hasil berjalan:

Selepas mengklik butang, konsol pelayan mencetak:

4.png

5. Sarung versi dipertingkatkan: Piggy Simple Chat Room

Cuma klik butang, dan kemudian pelayan mengembalikan rentetan maklumat, kan ? Turun dan mari lakukannya Untuk membina ruang sembang yang sangat mudah, kita perlu menggunakan kumpulan benang untuk menyimpan koleksi pautan Socket Tulis benang demi bait, mari alami butiran dalam kod!

Rendering pelaksanaan:

Mula-mula jalankan pelayan kami:

5.png

Kemudian asingkan program kami Jalankan pada dua simulator:

6.gif

Seterusnya kita menulis kod:

Pertama ialah pelayan, iaitu untuk meletakkan operasi membaca dan menulis soket ke dalam benang tersuai, mencipta After ServerSocket, gelung Panggil kaedah terima Apabila pelanggan baharu mengakses, tambahkan soket pada koleksi dan buat urutan baharu dalam kumpulan benang!

Selain itu, dalam kaedah membaca maklumat, rentetan input dinilai Jika ia adalah rentetan bye, soket dikeluarkan daripada koleksi. Keluarkan dan tutupnya!

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();}  
			}
		}
		
	}
}

Kemudian kepada klien, kesukaran klien adalah untuk mencipta benang lain, kerana Android tidak membenarkan langsung Lakukan operasi rangkaian dalam utas utama, dan jangan benarkan utas di luar utas utama untuk mengendalikan UI Pendekatan di sini adalah untuk mencipta sendiri yang baharu. A thread, dan mengemas kini UI melalui Hanlder Dalam pembangunan sebenar, tidak disyorkan untuk melakukan ini secara langsung! ! !

Fail reka letak: 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();
        }
    }
}

Ringkasan bahagian ini :

Baiklah, bahagian ini menerangkan komunikasi Soket berdasarkan TCP Artikel ini memperkenalkan model komunikasi Socket dan melaksanakan Contoh komunikasi Soket yang mudah, dan versi yang dipertingkatkan: Bilik Sembang Piggy, saya percaya ia akan berguna kepada mereka yang baru terlibat Pengaturcaraan soket memberi anda kemudahan~, terima kasih~