Android网络编程的Socket通信简述

2023-11-01

 

概述

      本文主要介绍Android中的网络编程的Socket通信一下小小总结。

创建服务器端的步骤
       1,指定端口实例化一个ServerSocket

2,调用ServerSocket的accept方法等待连接期间阻塞

3,获取位于底层的Socket流进行读写操作

4,将数据封装成流

5,对Socket进行读写

6,关闭流

创建客户端的步骤:

1,通过IP地址和端口实例化Socket,请求连接服务器

2,获取位于底层的Socket流进行读写操作

3,将数据封装成流(BufferedReader/PrintWriter,DataOutputStream/DataInputStream)的实例

4,对Socket进行读写

5,关闭流

使用ServerSocket创建服务器端:

 

public static void main(String[] args) throws IOException {
        // TODO Auto-generated method stub
          //创建一个ServerSo查看特,用于监听客户端Socket的连接请求
           ServerSocket ss=new  ServerSocket(3000);
           while(true){
               //每当接收到客户端Socket的请求,服务器端也对应产生一个Socket,没接收到请求就等待。。
               Socket s=ss.accept();
               OutputStream os=s.getOutputStream();//服务器端产生的Socket获取输出流
               os.write("您好,您收到了来自服务器的祝福!\n".getBytes());
               os.close();
               s.close();
           }
    }

 

客户端使用Socket通信:
测试环境是PC端服务器,手机当客户端,PC和手机要连接同一个局域网,PC和手机在同一网段

package com.example.simpleclient;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.net.UnknownHostException;

import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.TextView;


public class MainActivity extends Activity {
     TextView text;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        text=(TextView) findViewById(R.id.text);
        new Thread(){

            @Override
            public void run() {
                // TODO Auto-generated method stub
                                     
                    try {
                        //建立连接到远程服务器的的Socket,Ip是服务器端PC的IP,测试环境是PC端服务器,手机当客户端,PC和手机要连接同一个局域网,PC和手机在同一网段
                        Socket socket = new Socket("192.168.88",3000);
                        //将Socket对应的输入流包装秤BufferedReader
                        BufferedReader br=new BufferedReader(new InputStreamReader(socket.getInputStream()));
                        String line=br.readLine();
                        text.setText("来自服务的数据:"+line);
                        br.close();
                        socket.close();
                    } catch (UnknownHostException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }                                  
            }
             
        }.start();
    }
    
}

 

1
<!-- 访问网络权限 -->

客户端和服务器端的输入输出流的问题容易搞混淆:如下图

 

\

在客户端:

socket.getInputStream();从socket读来自服务器的数据

socket.getOutputStream();向socket中写数据,传给服务器,服务器在它的socket的输入流读这个数据

在服务器端:

socket.getInputStream();从socket读来自客户端的数据

socket.getOutputStream();向socket中写数据,传给客户端,客户端在它的socket的输入流读这个数据

就是说客户端和服务器端的输入输出流是对应的,输入流连接到输出流

输入输出流的包装:

第一种方法:数据二进制流

DataInputStream in=new DataInputStream(socket.getInputStream());//接收客户端信息
DataOutputStream out=new DataOutputStream(socket.getOutputStream());  //向客户端发送消息

 

第二种方法:

PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())),true);
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));

 

socketClient,java

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

public class socketClient extends Activity {
    private Button button;
    private TextView text;
    private EditText edit;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        button = (Button) findViewById(R.id.button);
        edit = (EditText) findViewById(R.id.edit);
        text = (TextView) findViewById(R.id.text);

        button.setOnClickListener(new View.OnClickListener() {
            private Socket socket = null;

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub

                String sendMsg = edit.getText().toString() + "\r\n";

                try {
                    socket = new Socket("192.168.0.37", 8888); // 创建Socket,其中ip地址为我的PC机器的地址,手机通过wifi上网和服务器在一个网段

                    // PrintWriter out = new PrintWriter(new BufferedWriter(new
                    // OutputStreamWriter(socket.getOutputStream())),true);
                    // out.println(sendMsg);
                    //                 
                    // BufferedReader in = new BufferedReader(new
                    // InputStreamReader(socket.getInputStream()));
                    // String readMsg = in.readLine();
                    // if(readMsg !=null){
                    // text.setText(readMsg);
                    // }else{
                    // text.setText("错误");
                    // }
                    //                 
                    // out.close();
                    // in.close();
                    // socket.close();

                    DataOutputStream out = new DataOutputStream(socket
                            .getOutputStream()); // 向服务器发送消息
                    out.writeUTF(sendMsg);
                    out.flush();

                    DataInputStream in = new DataInputStream(socket
                            .getInputStream()); // 接收来自服务器的消息
                    String readMsg = in.readUTF();
                    if (readMsg != null) {
                        text.setText(readMsg);
                    }
                    out.close();
                    in.close();
                    socket.close();

                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }
}

 


Server.java

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;

public class Server {
    public Server(){
        new ServerThread().start();
    }
    class ServerThread extends Thread{
        public void run() {
            try {
                ServerSocket ss=new ServerSocket(8888); 创建一个ServerSocket对象,并让这个ServerSocket在8888端口监听
                while(true){
                    Socket socket=ss.accept(); //调用ServerSocket的accept()方法,接受客户端所发送的请求,如果客户端没有发送数据,那么该线程就停滞不继续
//                  try {
//                      BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));  //接收客户端信息
//                      String readline = in.readLine();
//                      System.out.println("readline:"+readline);
//                     
//                      PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())),true);
//                      out.println("link server success");
//                     
//                      in.close();   //关闭流
//                      out.close();//关闭流
//                      socket.close();//关闭打开的socket
//                     
//                  } catch (Exception e) {
//                      // TODO: handle exception
//                  }finally{
//                  //  socket.close();//
//                  }
                    try {
                        DataInputStream in=new DataInputStream(socket.getInputStream());//接收客户端信息
                        String readline=in.readUTF();
                        System.out.println(readline);
                             
                        DataOutputStream out=new DataOutputStream(socket.getOutputStream());  //向客户端发送消息
                        out.writeUTF("link server success");
                        out.flush();
                         
                        in.close();   //关闭流
                        out.close();//关闭流
                        socket.close();//关闭打开的socket
                         
                    } catch (Exception e) {
                        System.out.println(e.getMessage());
                    }
                }
            } catch (IOException e) {
                System.out.println(e.getMessage());
            }
        }
    }
    public static void main(String[] args) throws IOException {
        new Server();   //开启服务器
    }
     

}
 


加入多线程:聊天室

客户端和服务器端保持长时间的通信,服务器需要不断的读取客户端数据,并向客户端写入数据,客户端也需要不断的读取服务器的数据

服务器应该为每个Socket单独启动一条线程,每条线程负责与一个客户端进行通信

服务器端:

package com.hust.multithred;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;

public class MyServer {

    /**
     * @param args
     * @throws IOException
     */
    //服务器端保存所有Socket的ArrayList
    public static  ArrayList<socket> socketlist=new ArrayList<socket>();
     
    public static void main(String[] args) throws IOException {
        // TODO Auto-generated method stub
       
       ServerSocket ss=new ServerSocket(3000);//ServerSocket监听3000端口
       while(true){
           Socket socket_in_server=ss.accept();//循环等待客户端的Socket
           socketlist.add(socket_in_server);   //每接收到一个客户端的Socket,将服务器端产生的与之对应的Socket加入数组
           //为每一个Socket单独启动一条线程,每个线程负责与一个客户端进行通信
           SocketThread socketthread=new SocketThread(socket_in_server);
           new Thread(socketthread).start();
       }
        
    }
     

}
package com.hust.multithred;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;

public class SocketThread implements Runnable{//线程任务类,实现Runnable接口
    Socket s=null;
    BufferedReader br=null;
    public SocketThread(Socket s) throws IOException{
        this.s=s;
        br=new BufferedReader(new InputStreamReader(s.getInputStream()));//Socket输入流包装成字符流,来自客户端的数据在此输入流上,服务器端可以读
    }
    public void run() {
        // TODO Auto-generated method stub
        try {
        String content=null;
        //循环不断冲Socket中读取客户端发送过来的数据
        while((content=readFormClient())!=null){
            //每读到数据之后,将读到的内容向每个Socket发送一次
            for(Socket s:MyServer.socketlist){                 
                    OutputStream os=s.getOutputStream();
                    os.write((content+"\n").getBytes("utf-8")); //写到每个socket 的输出流上             
            }
        }
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    //从输入流上读取来自客户端的数据方法
    public String readFormClient(){
        String content=null;
        try {
            content = br.readLine();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            MyServer.socketlist.remove(s);
        }
        return content;
    }
     
}


客户端:

MainActivity.java

package com.hust.multithreadclient;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

  
public class MainActivity extends Activity {
     EditText input;
     TextView show;
     Button send;
     Handler handler;
     ClientThread clientthread;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        input=(EditText) findViewById(R.id.input);
        show=(TextView) findViewById(R.id.show);
        send=(Button) findViewById(R.id.send);
        //此处handler接收来自子线程的消息,负责处理消息,更新UI
        handler=new Handler(){

            @Override
            //如果消息来自子线程
            public void handleMessage(Message msg) {
                // TODO Auto-generated method stub
                if(msg.what==0x123){
                    show.append("\n"+msg.obj.toString());
                }
            }
             
        };
        //客户端启动ClientThread线程创建玩过连接,读取来自服务器的数据
        new Thread(new ClientThread(handler)).start();
         
         
        send.setOnClickListener(new OnClickListener(){

            @Override
            public void onClick(View v) {
                // 当用户按下发送按钮后,将用户输入的数据封装成Message,发给子线程的Handler,此处handler负责发送消息
                Message msg=new Message();
                msg.what=0x111;
                msg.obj=input.getText().toString();
                clientthread.rvhandler.sendMessage(msg);//发给子线程的Handler
                input.setText("");
            }          
        });
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();
        if (id == R.id.action_settings) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }
}

 


ClientThread.java

package com.hust.multithreadclient;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;

import android.os.Handler;
import android.os.Looper;
import android.os.Message;

public class ClientThread implements Runnable {
     Socket s;
     Handler handler;   //定义向UI线程发送消息的Handler对象
     Handler rvhandler; //定义接收UI线程消息的Handler对象
      
     BufferedReader br=null;
     OutputStream os=null;
     public ClientThread(Handler handler){
         this.handler=handler;
     }
    @Override
    public void run() {
        // TODO Auto-generated method stub
           try {
            s=new Socket("192.168.1.88",3000);
            br=new BufferedReader(new InputStreamReader(s.getInputStream()));
            os=s.getOutputStream();
            //启动一条子线程来读取服务器端相应的数据
            new Thread(){

                @Override
                public void run() {
                    // TODO Auto-generated method stub
                    String content=null;
                    try{
                        while((content=br.readLine())!=null){
                            Message msg=new Message();
                            msg.what=0x123;
                            msg.obj=content;
                            handler.sendMessage(msg);//此子线程中仅仅是读来自服务器的数据,并发给UI线程的Handler处理
                        }
                         
                    }catch (IOException e) {
                        // TODO Auto-generated catch block
                          e.printStackTrace();
                     }
                }
                 
            }.start();
            /*
             * 当前客户端线程中Handler,Android线程之间的通信是Handler来实现
             * 此Hnadler接收UI线程发过来的数据,即用户的输入,并写到输出流
             * 因为此Handler是接收处理消息,所以需要使用Looper
             * */
            Looper.prepare();
            rvhandler=new Handler(){

                @Override
                public void handleMessage(Message msg) {
                    //如果接收到UI线程中用户输入的数据
                    if(msg.what==0x111){
                        try{
                            //将用户在文本框内的输入内容写入网络
                            os.write((msg.obj.toString()+"\r\n").getBytes("utf-8"));
                        }catch(IOException e){
                            e.printStackTrace();                           
                        }
                    }
                }
                 
            };
            Looper.loop();//启动looper
             
           } catch (UnknownHostException e) {
            // TODO Auto-generated catch block
               e.printStackTrace();
          } catch (IOException e) {
            // TODO Auto-generated catch block
              e.printStackTrace();
           }
    }

}
 
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android网络编程的Socket通信简述 的相关文章

  • Android Studio JNI开发入门教程

    概述 在Andorid Studio不支持JNI开发之前大家一般都是使用Eclipse开发JNI 各种配置让人觉得很蛋疼 从Andorid Studio支持JNI开发后 让我们开发JNI变的如此简单 下面我就介绍一下Android Stud
  • Android BLE 快速开发示例

    目录 概述 1 FastBle的使用 2 BLE开发实践方面的理解 3 FastBle源码解析 概述 思来想去 还是写这篇博文 记录一下 当时学习BLE的一些心得 重捡回当前Android知识 想深入了解蓝牙通讯知识 这个案例是非常不错的选
  • android 注册页面实现

    自己动手做的第一个demo 简单的注册页面的实现 并且注册成功后返回注册信息 适用于android新手基本控件的使用 注册页面的实现 import android os Bundle import android app Activity
  • 关于软件设计使用中一些的原则简述

    概述 向大家介绍过一些软件开发的原则 比如优质代码的十诫和Unix传奇 下篇 中所以说的UNIX的设计原则 相信大家从中能够从中学了解到一些设计原理方面的知识 正如我在 再谈 我是怎么招聘程序 中所说的 一个好的程序员通常由其操作技能 知识
  • 从Map中 取出第一个key/第一个value的方法

    从Map中取出第一个 key 和 value 的方法 使用Map Entry进行操作 可与LinckedHashMap 按元素存入顺序排序的有序Hash表 搭配使用 实现特定的业务要求 获取map中第一个key值 param map 数据源
  • Android网络编程的Socket通信简述

    概述 本文主要介绍Android中的网络编程的Socket通信一下小小总结 创建服务器端的步骤 1 指定端口实例化一个ServerSocket 2 调用ServerSocket的accept方法等待连接期间阻塞 3 获取位于底层的Socke
  • SVN文件夹图标不正常显示解决方案(win10)android studio

    在使用Android Studio提交代码时发现svn图标莫名其妙的不显示 其他操作都正常 在网上搜了一堆资料都有各种说法 结合了操作 一步步来试终于给我找到了 在这我自己总结一下 一部分也是拷贝别的图片 写一篇清楚文章好希望能帮助和我遇到
  • Android studio安装教程(2020/11/20最新版本的安装)

    一 安装前提 系统已经安装了jdk 而且版本在1 8以上 打开命令提示符界面 输入java version 切记之间有空格 就可以查看自己jdk安装版本了 二 安装准备 在官网下载最新安装包 接收协议进行下载 三 安装步骤 双击安装包 点击
  • Android adb 输出指定app 错误日志

    查看错误日志 adb logcat E 按照时间查看日志 adb logcat v time
  • 2019最新 国内唯一的Android从程序员到架构师全套教程

    课程目标 国内唯一的Android从程序员到架构师全套视频教程 适用人群 Android开发至少两年经验的IT工程师 想深入了解Android开源平台的资深工程师 Android项目团队技术管理者 课程概述 遵循敏捷的迭代过程 从思想 方法
  • java 字符串示例

    概述 最近项目上 需求 需要Android端在一段字符串分包处理 在此做个笔录 1 code public class Main public static void main String args System out println
  • ubuntu搭建android编译环境

    本文来自linux与嵌入式技术Q群52240781 ubuntu12 04 14 04安装后搭建android编译环境 注安装的是64位ubuntu系统12 04或14 04 请安装ubuntu的LTS版即12 04或14 04 每2年发布
  • Android SIM卡识别加载流程

    文章目录 总述 代码路径 UICC框架 SIM卡识别加载流程 日志分析举例 总述 本文基于Android N Android 7 首先要知道SIM卡一般是挂载在CP侧 MODEM侧 的 由MODEM给予真正的上电 识别 通信等 然后通过AP
  • Unity Android 长时间运行导致卡死的BUG

    抛出问题 最近项目中遇到一个问题 Unity 项目打包成 Android 长时间运行会导致 App 卡死 该问题出现在Unity 2021 3 19其他版本不详 由于项目中引入了arr库所以查找问题比较难受 好在搞安卓的同事帮忙研究了一下
  • Android NDK是什么

    官方给出的答案 Android NDK 是一套允许您使用原生代码语言 例如 C 和 C 实现部分应用的工具集 在开发某些类型应用时 这有助于您重复使用以这些语言编写的代码库 深入的学习 https developer android goo
  • Android 报错 : FATAL EXCEPTION:main 解决方法

    今天安卓开发课上碰到的新问题 前景提示 老师让我们自己试一下那个两个页面跳转的效果 于是我就开始写了 然后报错 解决方法 逐一排查 首先要看你mainfest xml里面有没有增加Activity 当然我是加了 但是他还报错 具体代码界面
  • Android Studio工具使用技巧

    作为一个Android开发者 熟练使用开发工具能让你工作效率提高 能让你少点加班 剩下时间学习其他的知识 是个多么好的事情 想高级攻城狮方向迈进 不费话了 直接进去主题 一 模版 1 1 for循环的使用 遍历集合的时候 对象 for就可以
  • 【Android Studio】Design editor is unavailable until next gradle sync.如何解决?

    Design editor is unavailable until next gradle sync 如何解决 打开一个网上开源的下载文件 在查看安卓页面布局 也就是控件布局时 会出现一个bug Design editor is unav
  • 升级SQLite数据库

    一 步骤 1 在之前的基础上添加一张Category表 在onCreate 方法中执行建CREATE CATEGORY表语句 2 然后在onUpgrade 中执行两条drop语句 发现数据库表存在 就将已经存在的表格删除 再在onCreat
  • The style on this component requires your app theme to be Theme.MaterialComponents

    MD版本采用如下 implementation com google android material material 1 2 0 alpha01 再采用MD的Dialog的时候报标题错误 后经分析查找 当前版本强制APP主题为Mater

随机推荐