当前位置:   article > 正文

(原创)Socket开发入门与实例_android socket编程

android socket编程

Socket是Java网络编程的基础

了解Socket通信,在java和android开发中都有用处

那么现在就来大概说下

如何搭建服务端和客户端

从而实现Socket通信的

首先我们从java方面开始讲起

服务端代码具体如下:

/**
 * Created by THINK on 2018/6/4.
 * 服务端
 */
public class SocketService {
    public static void main(String[] args) {
        try {
            //设置服务端端口号
            ServerSocket server = new ServerSocket(10086);
            System.out.println("服务器已经准备就绪");
            Socket socket = server.accept();//堵塞方法,等待客户端接入
            System.out.println("有一个客户已经连接");
            new SocketThread(socket).start();//开启接收内容的线程
            Scanner scanner = new Scanner(System.in);//键盘输入类
            while (true) {
                //给客户发一条消息
                OutputStream out = socket.getOutputStream();
                String str = scanner.next();
                out.write(str.getBytes());
                //接受客户端发来的消息
//                InputStream in = socket.getInputStream();
//                byte[] bytes = new byte[1024];
//                int count = in.read(bytes);
//                System.out.println("收到的字节数" + count);
//                System.out.println("接受到客户消息:" + new String(bytes).trim());
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

这里需要注意几点

1) 每个ip地址对应一个端口号,确保连接的唯一性

2) 接受和发送都采用输入输出流的形式,所以要先了解java中I/O流的知识

3) 接受消息我单独封装成了一个线程,这样收发消息的操作各自独立。代码如下

/**
 * Created by THINK on 2018/6/4.
 * 服务端接收消息的线程
 */
public class SocketThread extends Thread {
    private Socket socket;
    private InputStream in;


    public SocketThread(Socket socket) {
        try {
            in = socket.getInputStream();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void run() {
        while (true) {
            byte[] bs = new byte[1024];
            try {
                int count = in.read(bs);
                System.out.println("获取用户输入的内容" + new String(bs, 0, count));
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

下面是客户端的配置了

主要需要的是ip地址和端口号

端口号需要双方协商

确保唯一性就好

/**
 * Created by THINK on 2018/6/4.
 * 客户端
 */
public class Client {
    public static void main(String[] args) {
        //创建客户端的Socket对象
        try {
            Socket socket = new Socket("127.0.0.1", 10086);
            System.out.println("连接服务器");
            new ClientThread(socket).start();
            Scanner scanner = new Scanner(System.in);
            while (true) {
//                InputStream in = socket.getInputStream();
//                byte[] bs = new byte[1024];
//                in.read(bs);//堵塞方法 等待消息进来
//                System.out.println("main: 接受到服务器的消息:" + new String(bs).trim());
                //发送消息给服务端
                OutputStream out = socket.getOutputStream();
                String str = scanner.next();
                out.write(str.getBytes());
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

这里需要注意:

1)这里的ip地址填写的是本机地址,你们可以根据需求设置不同的ip地址

2)客户端接受消息仍然是新建了一个独立线程,代码如下

/**
 * Created by THINK on 2018/6/4.
 * 客户端接收消息的线程
 */
public class ClientThread extends Thread {
    private Socket socket;
    private InputStream in;
    public ClientThread(Socket socket) {
        try {
            in = socket.getInputStream();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void run() {
        while (true) {
            byte[] bs = new byte[1024];
            try {
                int count = in.read(bs);
                System.out.println("获取服务器输入的内容" + new String(bs, 0, count));
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

以上就是java代码来实现Socket通信的简单实例了

下面开始在安卓端实现这个Socket通信

这里采用的是开启服务(Service)的方式

首先需要相关权限

<!--允许应用程序改变网络状态-->
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />

<!--允许应用程序改变WIFI连接状态-->
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />

<!--允许应用程序访问有关的网络信息-->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

<!--允许应用程序访问WIFI网卡的网络信息-->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />

<!--允许应用程序完全使用网络-->
<uses-permission android:name="android.permission.INTERNET" />

然后记得注册Service,并且在你需要通信的地方开启Service

<!--注册服务-->
<service android:name="com.socket.demo.ziliao.SocketService" />

这里我选择在主界面放置一个按钮,用来发送广播给Service

通知Service发送消息给Socket服务端

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //启动核心服务
        Intent intent = new Intent(this, com.socket.demo.ziliao.SocketService.class);
        startService(intent);
        findViewById(R.id.sockettxt).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent("socket");
                intent.putExtra("socketString", "发送消息给Socket服务端");
                sendBroadcast(intent);
            }
        });

    }
}

最后是Service页面源代码

public class SocketService extends Service {

    /**
     * 主机IP地址
     */
    public static String HOST = "127.0.0.1";

    /**
     * 端口号
     */
    public static final int PORT = 6666;
    private Socket socket;//socket连接


    //接收主界面广播
    private BroadcastReceiver broadcastReceiver;

    @Override
    public void onCreate() {
        super.onCreate();
        broadcastReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                switch (intent.getAction()) {
                    case "socket"://收到广播
                        String socketString = intent.getStringExtra("socketString");
                        new SendMsgThread(socketString).start();//开启发送消息线程
                        break;
                }

            }
        };
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction("socket");//添加过滤器
        registerReceiver(broadcastReceiver, intentFilter);//广播注册
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        new InitSocketThread().start();
        return super.onStartCommand(intent, flags, startId);
    }


    /**
     * 开启线程连接服务器
     */
    public class InitSocketThread extends Thread {
        @Override
        public void run() {
            try {
                socket = new Socket(HOST, PORT);
                socket.setKeepAlive(true);//
                Log.d("print", "socketIP:" + HOST);
                if (socket.isConnected()) {//判断是否连接成功
                    if (!socket.isClosed() && !socket.isOutputShutdown()) {
                        OutputStream os = socket.getOutputStream();
                        os.write("我是熊叶平,这是我这边发过来的消息".getBytes());
                        os.flush();
                    }
                    new ReadThread(socket).start();//开启接受线程

                } else {
                    Log.d("print", "socket断开了");
                }
            } catch (SocketException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
    }

    /**
     * 开启线程给Socket服务端发送消息
     */
    public class SendMsgThread extends Thread {

        private String str_socket;

        public SendMsgThread(String str_socket) {
            this.str_socket = str_socket;
        }

        @Override
        public void run() {
            try {
                if (socket.isConnected()) {//判断是否连接成功
                    if (!socket.isClosed() && !socket.isOutputShutdown()) {
                        OutputStream os = socket.getOutputStream();
                        os.write(str_socket.getBytes());
                        os.flush();
                    }
                } else {
                    Log.d("print", "socket断开了");
                }
            } catch (SocketException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
    }


    /**
     * 开启线程接收Socket服务端消息
     */
    public class ReadThread extends Thread {
        private Socket rSocket;

        public ReadThread(Socket socket) {
            rSocket = socket;
        }


        @SuppressLint("NewApi")
        @Override
        public void run() {
            super.run();
            if (null != rSocket && !rSocket.isClosed() && !rSocket.isInputShutdown()) {
                InputStreamReader isr = null;//获取socket获取到的输入流,并设置编码格式
                try {
                    isr = new InputStreamReader(rSocket.getInputStream(), "UTF-8");
                    char[] by = new char[1024];  //一次读1024个字节
                    while (isr != null) {
                        int read = isr.read(by);//服务器数据未发过来时,堵塞在这里等待
                        Message msg = handler.obtainMessage();
                        msg.what = 1;//只能放数字
                        /**这里注意:因为读的是1024个字节,但是有可能服务器发送的没有1024个,这样你读到不够的时候系统默认就会打上空格,空格在Log就会是乱码,解决办法就是利用string的构造传入一个输入流,从0开始读取,读完结束,即可去掉所有空格*/
                        msg.obj = new String(by, 0, read);//用来放对象
                        handler.sendMessage(msg);// 结果返回给UI处理
                    }
                } catch (Exception e) {
                    Log.e("print", "socket连接失败");
                    try {
                        Thread.sleep(1000);// 延时
                        Log.e("print", "socket连接失败");
                        //连接出错时再次调用这个方法,实现重连
                        new InitSocketThread().start();
                    } catch (Exception io) {

                    }
                }
            }
        }

    }

    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
                case 1:
                    /**socket就是服务端发送的数据*/
                    final String socket = msg.obj.toString();
                    Log.d("print", "handleMessage: " + socket);
            }
        }
    };


    @Override
    public void onDestroy() {
        super.onDestroy();
        if (broadcastReceiver != null) {
            //取消广播注册
            unregisterReceiver(broadcastReceiver);
        }
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

}

以上就是Android端Socket通信的简单实现

其实在实际开发中

Socket通信可能会遇到不同的开发需求

但是只要掌握了这种通信方式

根据不同的需求去做相应的代码结构设计

熟能生巧

还是没有太大的问题的。

最后祝大家工作愉快,天天进步!

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/不正经/article/detail/271992
推荐阅读
相关标签
  

闽ICP备14008679号