tongyu24的个人博客分享 http://blog.sciencenet.cn/u/tongyu24

博文

[转载]android socket编程实例

已有 876 次阅读 2019-8-13 08:43 |系统分类:教学心得|文章来源:转载

android socket编程实例

android客户端通过socket与服务器进行通信可以分为以下几步:
应用程序与服务器通信可以采用两种模式:TCP可靠通信 和UDP不可靠通信。
(1)通过IP地址和端口实例化Socket,请求连接服务器:
     socket = new Socket(HOST, PORT);   //host:为服务器的IP地址  port:为服务器的端口号
(2)获取Socket流以进行读写,并把流包装进BufferWriter或者PrintWriter:
   PrintWriter out = new PrintWriter( new BufferedWriter( new OutputStreamWriter(socket.getOutputStream())),true);  
   这里涉及了三个类:socket.getOutputStream得到socket的输出字节流,OutputStreamWriter是字节流向字符流转换的桥梁,BufferWriter是字符流,然后再包装进PrintWriter。
(3)对Socket进行读写

     if (socket.isConnected()) {                    if (!socket.isOutputShutdown()) {
                        out.println(msg);
                    }
                }

(4)关闭打开的流

  out.close();

在写代码的过程中一定要注意对socket  输入流  输出流的关闭

下面是一个简单的例子:
main.xml

复制代码

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    android:orientation="vertical"
    android:layout_width="fill_parent"  
    android:layout_height="fill_parent">  
    <TextView        android:id="@+id/TextView"
        android:singleLine="false"  
        android:layout_width="fill_parent"  
        android:layout_height="wrap_content" />  
    <EditText android:hint="content"
        android:id="@+id/EditText01"  
        android:layout_width="fill_parent"  
        android:layout_height="wrap_content">  
    </EditText>  
    <Button        android:text="send"
        android:id="@+id/Button02"  
        android:layout_width="fill_parent"  
        android:layout_height="wrap_content">  
    </Button>  </LinearLayout>

复制代码

下面是android客户端的源代码:

复制代码

package com.android.SocketDemo;import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.IOException;import java.io.InputStreamReader;import java.io.OutputStreamWriter;import java.io.PrintWriter;import java.net.Socket;import android.app.Activity;import android.app.AlertDialog;import android.content.DialogInterface;import android.os.Bundle;import android.os.Handler;import android.os.Message;import android.view.View;import android.widget.Button;import android.widget.EditText;import android.widget.TextView;public class SocketDemo extends Activity implements Runnable {    private TextView tv_msg = null;    private EditText ed_msg = null;    private Button btn_send = null;//    private Button btn_login = null;
    private static final String HOST = "192.168.1.223";    private static final int PORT = 9999;    private Socket socket = null;    private BufferedReader in = null;    private PrintWriter out = null;    private String content = "";    /** Called when the activity is first created. */
    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        tv_msg = (TextView) findViewById(R.id.TextView);
        ed_msg = (EditText) findViewById(R.id.EditText01);//        btn_login = (Button) findViewById(R.id.Button01);
        btn_send = (Button) findViewById(R.id.Button02);        try {
            socket = new Socket(HOST, PORT);
            in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(
                    socket.getOutputStream())), true);
        } catch (IOException ex) {
            ex.printStackTrace();
            ShowDialog("login exception" + ex.getMessage());
        }
        btn_send.setOnClickListener(new Button.OnClickListener() {
            @Override            public void onClick(View v) {                // TODO Auto-generated method stub
                String msg = ed_msg.getText().toString();                if (socket.isConnected()) {                    if (!socket.isOutputShutdown()) {
                        out.println(msg);
                    }
                }
            }
        });        //启动线程,接收服务器发送过来的数据
        new Thread(SocketDemo.this).start();
    }    //如果连接出现异常,弹出AlertDialog!
    public void ShowDialog(String msg) {        new AlertDialog.Builder(this).setTitle("notification").setMessage(msg)
                .setPositiveButton("ok", new DialogInterface.OnClickListener() {
                    @Override                    public void onClick(DialogInterface dialog, int which) {                        // TODO Auto-generated method stub                    }
                }).show();
    }    //读取服务器发来的信息,并通过Handler发给UI线程
    public void run() {        try {            while (true) {                if (socket.isConnected()) {                    if (!socket.isInputShutdown()) {                        if ((content = in.readLine()) != null) {
                            content += "\n";
                            mHandler.sendMessage(mHandler.obtainMessage());
                        } else {
                        }
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }    //接收线程发送过来信息,并用TextView显示
    public Handler mHandler = new Handler() {        public void handleMessage(Message msg) {            super.handleMessage(msg);
            tv_msg.setText(tv_msg.getText().toString() + content);
        }
    };
}

复制代码

下面是服务器端得java代码:

复制代码

import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.IOException;import java.io.InputStreamReader;import java.io.OutputStreamWriter;import java.io.PrintWriter;import java.net.ServerSocket;import java.net.Socket;import java.util.ArrayList;import java.util.List;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;public class Main {    private static final int PORT = 9999;    private List<Socket> mList = new ArrayList<Socket>();    private ServerSocket server = null;    private ExecutorService mExecutorService = null; //thread pool
    
    public static void main(String[] args) {        new Main();
    }    public Main() {        try {
            server = new ServerSocket(PORT);
            mExecutorService = Executors.newCachedThreadPool();  //create a thread pool
            System.out.print("服务器已启动...");
            Socket client = null;            while(true) {
                client = server.accept();                //把客户端放入客户端集合中                mList.add(client);
                mExecutorService.execute(new Service(client)); //start a new thread to handle the connection            }
        }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 = "user" +this.socket.getInetAddress() + "come toal:"
                        +mList.size();                    this.sendmsg();
                } catch (IOException e) {
                    e.printStackTrace();
                }           
            }
            @Override            public void run() {                // TODO Auto-generated method stub
                try {                    while(true) {                        if((msg = in.readLine())!= null) {                            //当客户端发送的信息为:exit时,关闭连接
                            if(msg.equals("exit")) {
                                System.out.println("ssssssss");
                                mList.remove(socket);
                                in.close();
                                msg = "user:" + socket.getInetAddress()                                    + "exit total:" + mList.size();
                                socket.close();                                this.sendmsg();                                break;                                //接收客户端发过来的信息msg,然后发送给客户端。
                            } 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())),true);
                       pout.println(msg);
                   }catch (IOException e) {
                       e.printStackTrace();
                   }
               }
           }
        }    
}

复制代码

注意在AndroidManifest.xml中加入对网络的访问权限
<uses-permission android:name="android.permission.INTERNET"></uses-permission>

在写代码的过程中一定要注意对套接字和输入/输出流的关闭

解析:除了isClose方法,Socket类还有一个isConnected方法来判断Socket对象是否连接成功。  看到这个名字,也许读者会产生误解。  其实isConnected方法所判断的并不是Socket对象的当前连接状态,  而是Socket对象是否曾经连接成功过,如果成功连接过,即使现在isClose返回true, isConnected仍然返回true。因此,要判断当前的Socket对象是否处于连接状态, 必须同时使用isClose和isConnected方法, 即只有当isClose返回false,isConnected返回true的时候Socket对象才处于连接状态。 虽然在大多数的时候可以直接使用Socket类或输入输出流的close方法关闭网络连接,但有时我们只希望关闭OutputStream或InputStream,而在关闭输入输出流的同时,并不关闭网络连接。这就需要用到Socket类的另外两个方法:shutdownInput和shutdownOutput,这两个方法只关闭相应的输入、输出流,而它们并没有同时关闭网络连接的功能。和isClosed、isConnected方法一样,Socket类也提供了两个方法来判断Socket对象的输入、输出流是否被关闭,这两个方法是isInputShutdown()和isOutputShutdown()。 shutdownInput和shutdownOutput并不影响Socket对象的状态。

 super.onCreate(savedInstanceState);

        // android3.0以后需要加入以下的代码,否则会报socket连接异常的错误
        StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder().detectDiskReads().detectDiskWrites().detectNetwork().penaltyLog().build()); 
        StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder().detectLeakedSqlLiteObjects().penaltyLog().penaltyDeath().build());  

        setContentView(R.layout.activity_login);




http://blog.sciencenet.cn/blog-3417471-1193425.html


下一篇:[转载]PC电脑和Android模拟器访问及模拟器之间tcp/udp通信

0

该博文允许注册用户评论 请点击登录 评论 (0 个评论)

数据加载中...
扫一扫,分享此博文

Archiver|手机版|科学网 ( 京ICP备14006957 )

GMT+8, 2019-10-23 21:09

Powered by ScienceNet.cn

Copyright © 2007- 中国科学报社

返回顶部