Communication Socket basée sur le protocole TCP (1) Classification Tutoriel d'introduction de base Android
Introduction à cette section :
La leçon conceptuelle de la section précédente était ennuyeuse, n'est-ce pas, mais il y a toujours quelque chose de gratifiant, n'est-ce pas ? le protocole TCP Pour la communication, comprenons d'abord le concept de Socket, le modèle de communication Socket, les étapes de mise en œuvre de Socket et en tant que service Socket Le client et le client doivent chacun faire ce qu'ils ont envie de faire ! D'accord, déboguons ce Socket du moins profond au plus profond !
Qu'est-ce que Socket ?
2. Modèle de communication Socket :
Analyse des étapes de mise en œuvre de la communication Socket :
Étape 1 : Créer un ServerSocket et un Socket
Étape 2 : Ouvrir l'entrée/sortie du Socket connecté diffuser
Étape 3 : Lire/écrire le Socket selon le protocole
Étape 4 : Fermer Flux d'entrée et de sortie, et Socket
D'accord, écrivons ensuite un exemple simple. Après avoir démarré le serveur, le client clique sur le bouton puis se connecte au serveur. Et envoyez une chaîne de chaînes au serveur, indiquant que le serveur est connecté via le Socket~
3 Écriture du serveur Socket :
Les éléments dont le serveur a besoin. ce qu'il faut faire sont les suivants :
Étape 1 : Créer un objet ServerSocket et lier le port d'écoute
Étape 2 : Appelez la méthode accept() pour écouter la demande du client
Étape 3 : Une fois la connexion établie, lisez les informations de demande envoyées par le client via le flux d'entrée
Étape 4 : Envoyer les informations de réponse au client via le flux de sortie
Étape 5 : Fermer les ressources associées
Code implémentation :
Créez un projet Java directement sous Eclipse, puis collez-y le code Java !
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(); } }
Ensuite, nous exécutons le code et la console affichera :
D'accord, voici maintenant le client Android !
4. Écriture du client Socket :
Le client doit faire ces choses :
Étape 1 : Créez un objet Socket et spécifiez l'adresse et le numéro de port du serveur à lier
Étape 2 : Une fois le lien établi, envoyez les informations de demande au serveur via le flux de sortie
Étape 3 : Obtenir les informations de réponse du serveur via le flux de sortie
Étape 4 : Fermer les ressources associées
Implémentation du code :
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(); } }
Parce qu'Android n'autorise pas les opérations réseau dans le thread principal ( fil de discussion de l'interface utilisateur), nous devons le faire nous-mêmes Ouvrez un autre fil de discussion pour vous connecter au Socket !
Résultat d'exécution :
Après avoir cliqué sur le bouton, la console du serveur imprime :
5. Cas de la version améliorée : Piggy Simple Chat Room
Cliquez simplement sur un bouton, puis le serveur renvoie une chaîne d'informations. Cela doit être très ennuyeux, n'est-ce pas. ? Descendons et faisons-le Pour créer une salle de discussion très simple, nous devons utiliser un pool de threads pour stocker une collection de liens Socket. Écrivez un fil de discussion par octet, découvrons les détails dans le code !
Rendu de l'implémentation :
Lancer d'abord notre serveur :
Puis séparer nos programmes Exécuter sur deux simulateurs :
Ensuite, nous écrivons le code :
Le premier est le serveur, qui consiste à placer les opérations de lecture et d'écriture des sockets dans un thread personnalisé, à créer Après ServerSocket, une boucle Appelez la méthode accept. Lorsqu'un nouveau client accède, ajoutez le socket à la collection et créez un nouveau thread dans le pool de threads !
De plus, dans la méthode de lecture des informations, la chaîne d'entrée est jugée. S'il s'agit d'une chaîne d'au revoir, le socket est supprimé de la collection. Retirez-le et fermez-le !
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();} } } } }
Ensuite pour le client, la difficulté du client est de créer un autre thread, car Android ne permet pas directement Effectuez des opérations réseau dans le thread principal et n'autorisez pas les threads en dehors du thread principal à exploiter l'interface utilisateur. L'approche ici consiste à en créer un nouveau vous-même. Un fil de discussion et la mise à jour de l'interface utilisateur via Hanlder. Dans le développement réel, il n'est pas recommandé de le faire directement ! ! !
Fichier de mise en page : 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(); } } }
Résumé de cette section :
D'accord, cette section explique la communication Socket basée sur TCP. L'article présente le modèle de communication Socket et l'implémente. Un exemple simple de communication Socket, et une version améliorée de celui-ci : Piggy Chat Room, je pense que cela sera utile à ceux qui sont simplement impliqués La programmation Socket vous apporte de la commodité~, merci~