Android Socket连接

efbb 4年前

注意点:注册访问的网络权限;android中UI线程不能有访问网络的操作,否则会报android.os.NetworkOnMainThreadException的异常


<uses-permission         android:name="android.permission.INTERNET"/>



实例一

客户端

Android Socket连接

Java:

package com.android.xiong.simplesocket;        import java.io.BufferedReader;    import java.io.IOException;    import java.io.InputStreamReader;    import java.io.OutputStream;    import java.net.InetSocketAddress;    import java.net.Socket;    import java.net.SocketTimeoutException;        import android.app.Activity;    import android.os.Bundle;    import android.os.Handler;    import android.os.Message;    import android.view.Menu;    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 {        Socket socket = null;        String buffer = "";        TextView txt1;        Button send;        EditText ed1;        String geted1;        public Handler myHandler = new Handler() {            @Override            public void handleMessage(Message msg) {                if (msg.what == 0x11) {                    Bundle bundle = msg.getData();                    txt1.append("server:"+bundle.getString("msg")+"\n");                }            }            };            @Override        protected void onCreate(Bundle savedInstanceState) {            super.onCreate(savedInstanceState);            setContentView(R.layout.activity_main);            txt1 = (TextView) findViewById(R.id.txt1);            send = (Button) findViewById(R.id.send);            ed1 = (EditText) findViewById(R.id.ed1);            send.setOnClickListener(new OnClickListener() {                    @Override                public void onClick(View v) {                    geted1 = ed1.getText().toString();                    txt1.append("client:"+geted1+"\n");                    //启动线程 向服务器发送和接收信息                    new MyThread(geted1).start();                }            });            }            class MyThread extends Thread {                public String txt1;                public MyThread(String str) {                txt1 = str;            }                @Override            public void run() {                //定义消息                Message msg = new Message();                msg.what = 0x11;                Bundle bundle = new Bundle();                bundle.clear();                try {                    //连接服务器 并设置连接超时为5秒                    socket = new Socket();                    socket.connect(new InetSocketAddress("1.1.9.30", 30000), 5000);                    //获取输入输出流                    OutputStream ou = socket.getOutputStream();                    BufferedReader bff = new BufferedReader(new InputStreamReader(                            socket.getInputStream()));                    //读取发来服务器信息                    String line = null;                    buffer="";                    while ((line = bff.readLine()) != null) {                        buffer = line + buffer;                    }                                        //向服务器发送信息                    ou.write("android 客户端".getBytes("gbk"));                    ou.flush();                    bundle.putString("msg", buffer.toString());                    msg.setData(bundle);                    //发送消息 修改UI线程中的组件                    myHandler.sendMessage(msg);                    //关闭各种输入输出流                    bff.close();                    ou.close();                    socket.close();                } catch (SocketTimeoutException aa) {                    //连接超时 在UI界面显示消息                    bundle.putString("msg", "服务器连接失败!请检查网络是否打开");                    msg.setData(bundle);                    //发送消息 修改UI线程中的组件                    myHandler.sendMessage(msg);                } catch (IOException e) {                    e.printStackTrace();                }            }        }            @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;        }        }



XML:



<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"        xmlns:tools="http://schemas.android.com/tools"        android:layout_width="match_parent"        android:layout_height="match_parent"        android:paddingBottom="@dimen/activity_vertical_margin"        android:paddingLeft="@dimen/activity_horizontal_margin"        android:paddingRight="@dimen/activity_horizontal_margin"        android:paddingTop="@dimen/activity_vertical_margin"        tools:context=".MainActivity" >            <EditText             android:id="@+id/ed1"            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:hint="给服务器发送信息"/>        <Button             android:id="@+id/send"            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:layout_below="@id/ed1"            android:text="发送"/>        <TextView             android:id="@+id/txt1"            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:layout_below="@id/send"/>                            </RelativeLayout>



服务端

package com.android.net;        import java.io.IOException;    import java.net.ServerSocket;    import java.net.Socket;    import java.util.ArrayList;    import java.util.List;        public class AndroidService {                public static void main(String[] args) throws IOException {            ServerSocket serivce = new ServerSocket(30000);            while (true) {                //等待客户端连接                Socket socket = serivce.accept();                new Thread(new AndroidRunable(socket)).start();            }        }        }



package com.android.net;        import java.io.BufferedReader;    import java.io.BufferedWriter;    import java.io.IOException;    import java.io.InputStream;    import java.io.InputStreamReader;    import java.io.OutputStream;    import java.io.OutputStreamWriter;    import java.io.PrintWriter;    import java.net.Socket;        public class AndroidRunable implements Runnable {            Socket socket = null;            public AndroidRunable(Socket socket) {            this.socket = socket;        }            @Override        public void run() {            // 向android客户端输出hello worild            String line = null;            InputStream input;            OutputStream output;            String str = "hello world!";            try {                //向客户端发送信息                output = socket.getOutputStream();                input = socket.getInputStream();                BufferedReader bff = new BufferedReader(                        new InputStreamReader(input));                output.write(str.getBytes("gbk"));                output.flush();                //半关闭socket                  socket.shutdownOutput();                //获取客户端的信息                while ((line = bff.readLine()) != null) {                    System.out.print(line);                }                //关闭输入输出流                output.close();                bff.close();                input.close();                socket.close();                } catch (IOException e) {                e.printStackTrace();            }            }    }



实例二

客户端

Java



package com.android.xiong.sockettwotest;        import android.app.Activity;    import android.os.Bundle;    import android.os.Handler;    import android.os.Message;    import android.view.Menu;    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 = new Handler() {                    @Override                public void handleMessage(Message msg) {                    // 如果消息来自子线程                    if (msg.what == 0x123) {                        // 将读取的内容追加显示在文本框中                        show.append("\n" + msg.obj.toString());                    }                }            };            clientThread = new ClientThread(handler);            // 客户端启动ClientThread线程创建网络连接、读取来自服务器的数据            new Thread(clientThread).start();            send.setOnClickListener(new OnClickListener() {                    @Override                public void onClick(View v) {                    try {                        // 当用户按下按钮之后,将用户输入的数据封装成Message                        // 然后发送给子线程Handler                        Message msg = new Message();                        msg.what = 0x345;                        msg.obj = input.getText().toString();                        clientThread.revHandler.sendMessage(msg);                        input.setText("");                        } catch (Exception e) {                        }                }            });        }            @Override        public boolean onCreateOptionsMenu(Menu menu) {            getMenuInflater().inflate(R.menu.main, menu);            return true;        }        }



package com.android.xiong.sockettwotest;        import java.io.BufferedReader;    import java.io.IOException;    import java.io.InputStreamReader;    import java.io.OutputStream;    import java.net.InetSocketAddress;    import java.net.Socket;    import java.net.SocketTimeoutException;        import android.os.Handler;    import android.os.Looper;    import android.os.Message;        public class ClientThread implements Runnable {        private Socket s;        // 定义向UI线程发送消息的Handler对象        Handler handler;        // 定义接收UI线程的Handler对象        Handler revHandler;        // 该线程处理Socket所对用的输入输出流        BufferedReader br = null;        OutputStream os = null;            public ClientThread(Handler handler) {            this.handler = handler;        }            @Override        public void run() {            s = new Socket();            try {                s.connect(new InetSocketAddress("1.1.9.30", 3000), 5000);                br = new BufferedReader(new InputStreamReader(s.getInputStream()));                os = s.getOutputStream();                // 启动一条子线程来读取服务器相应的数据                new Thread() {                        @Override                    public void run() {                        String content = null;                        // 不断的读取Socket输入流的内容                        try {                            while ((content = br.readLine()) != null) {                                // 每当读取到来自服务器的数据之后,发送的消息通知程序                                // 界面显示该数据                                Message msg = new Message();                                msg.what = 0x123;                                msg.obj = content;                                handler.sendMessage(msg);                            }                        } catch (IOException io) {                            io.printStackTrace();                        }                    }                    }.start();                // 为当前线程初始化Looper                Looper.prepare();                // 创建revHandler对象                revHandler = new Handler() {                        @Override                    public void handleMessage(Message msg) {                        // 接收到UI线程的中用户输入的数据                        if (msg.what == 0x345) {                            // 将用户在文本框输入的内容写入网络                            try {                                os.write((msg.obj.toString() + "\r\n")                                        .getBytes("gbk"));                            } catch (Exception e) {                                e.printStackTrace();                            }                        }                    }                    };                 // 启动Looper                Looper.loop();                } catch (SocketTimeoutException e) {                Message msg = new Message();                msg.what = 0x123;                msg.obj = "网络连接超时!";                handler.sendMessage(msg);            } catch (IOException io) {                io.printStackTrace();            }            }    }



XML:



<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"        xmlns:tools="http://schemas.android.com/tools"        android:layout_width="match_parent"        android:layout_height="match_parent"        android:paddingBottom="@dimen/activity_vertical_margin"        android:paddingLeft="@dimen/activity_horizontal_margin"        android:paddingRight="@dimen/activity_horizontal_margin"        android:paddingTop="@dimen/activity_vertical_margin"        tools:context=".MainActivity" >            <EditText            android:id="@+id/input"            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:hint="@string/input" />        <Button             android:id="@+id/send"            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:text="@string/send"            android:layout_below="@id/input"/>        <TextView             android:id="@+id/show"            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:layout_below="@id/send"/>        </RelativeLayout>





服务端

package com.android.net;        import java.io.IOException;    import java.net.ServerSocket;    import java.net.Socket;    import java.util.ArrayList;    import java.util.List;        public class MyService {            // 定义保存所有的Socket        public static List<Socket> socketList = new ArrayList<Socket>();            public static void main(String[] args) throws IOException {            ServerSocket server = new ServerSocket(3000);            while(true){                Socket s=server.accept();                socketList.add(s);                //每当客户端连接之后启动一条ServerThread线程为该客户端服务                new Thread(new ServiceThreada(s)).start();                            }        }        }



package com.android.net;        import java.io.BufferedReader;    import java.io.IOException;    import java.io.InputStreamReader;    import java.io.OutputStream;    import java.net.Socket;        public class ServiceThreada implements Runnable {            // 定义当前线程处理的Socket        Socket s = null;        // 该线程所处理的Socket所对应的输入流        BufferedReader br = null;            public ServiceThreada(Socket s) {            this.s = s;            try {                br = new BufferedReader(new InputStreamReader(s.getInputStream()));            } catch (IOException e) {                e.printStackTrace();            }        }            @Override        public void run() {                String content = null;            //采用循环不断的从Socket中读取客户端发送过来的数据            while((content=readFromClient())!=null){                //遍历socketList中的每个Socket                //将读取到的内容每个向Socket发送一次                for(Socket s:MyService.socketList){                    OutputStream os;                    try {                        os = s.getOutputStream();                        os.write((content+"\n").getBytes("gbk"));                    } catch (IOException e) {                        // TODO Auto-generated catch block                        e.printStackTrace();                    }                                    }            }            }            // 定义读取客户端的信息        public String readFromClient() {            try {                return br.readLine();            } catch (Exception e) {                e.printStackTrace();            }            return null;        }        }




附:

一些记录:

把socket写成一个服务:


public class SocketService extends Service{        Thread mServiceThread;                Socket client;                @Override        public IBinder onBind(Intent intent) {            // TODO Auto-generated method stub            return null;        }            @Override        public void onCreate() {            // TODO Auto-generated method stub            super.onCreate();                        mServiceThread = new Thread(new SocketServerThread());        }            @Override        public void onStart(Intent intent, int startId) {            // TODO Auto-generated method stub            super.onStart(intent, startId);                        mServiceThread.start();        }            @Override        public void onDestroy() {            // TODO Auto-generated method stub            super.onDestroy();        }            public class SocketServerThread extends Thread {            private static final int PORT = 54321;                        private SocketServerThread(){            }                        @Override            public void run() {                try {                    ServerSocket server = new ServerSocket(PORT);                                        while(true){                        System.out.println("begin client connected");                        client = server.accept();                        System.out.println("client connected");                                                BufferedReader reader = new BufferedReader(new InputStreamReader(client.getInputStream()));                        System.out.println("read from client:");                                                String textLine = reader.readLine();                        if(textLine.equalsIgnoreCase("EXIT")){                            System.out.println("EXIT invoked, closing client");                            break;                        }                            System.out.println(textLine);                                                PrintWriter writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(client.getOutputStream())));                                                writer.println("ECHO from server: " + textLine);                        writer.flush();                                                writer.close();                        reader.close();                    }                                           } catch (IOException e) {                    // TODO Auto-generated catch block                    System.err.println(e);                }               }                    }    }


状态:

除了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对象的状态。