Android基于Socket的网络通信

来源:互联网 发布:网络兼职推广语 编辑:程序博客网 时间:2024/04/27 08:15

Socket用于在应用程序向网络发出请求或者应答网络请求。ServerSocket用于服务器端,Socket用在建立网络连接时。若连接成功,应用程序两段都会产生一个Socket实例,操作这个实例完成会话。对于一个网络连接,Socket是平等的,不会因为服务器端或在客户端而产生不同级别。Socket基于TCP链接,数据传输有保障,较适用于建立长时间链接。通常Socket编程应用于即时通讯。


------------------------------------------

Socket服务器搭建

public class MyServerSocket {   public static void main(String[] args) {            new ServerListener().start();   }}

public class ServerListener extends Thread {   @Override   public void run() {      //1-65535      try {         ServerSocket serverSocket = new ServerSocket(55555);         while (true) {            //accept阻塞主线程 使用新线程建立连接            Socket socket = serverSocket.accept();            JOptionPane.showMessageDialog(null, "有客户端链接到了本机的12345端口");            //将socket传递给新的线程            ChatSocket cs = new ChatSocket(socket);            cs.start();            ChatManager.getChatManager().add(cs);         }               } catch (IOException e) {         e.printStackTrace();      }   }      }

public class ChatSocket extends Thread {   Socket socket;   public ChatSocket(Socket s) {      this.socket = s;   }   //广播消息   public void out(String out) {      try {         socket.getOutputStream().write((out+"\n").getBytes("UTF-8"));      } catch (UnsupportedEncodingException e) {         e.printStackTrace();      } catch (IOException e) {         e.printStackTrace();      }   }   @Override   public void run() {      //读取接收的消息      try {         BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream(),"UTF-8"));         String line = null;         while ((line = br.readLine()) != null) {            System.out.println(line);            ChatManager.getChatManager().publish(this, line);         }         br.close();      } catch (UnsupportedEncodingException e) {         e.printStackTrace();      } catch (IOException e) {         e.printStackTrace();      }   }}

import java.util.Vector;public class ChatManager {   //聊天服务器只能有一个manager 故该类必须单例化   private ChatManager() {}   private static final ChatManager cm = new ChatManager();   public static ChatManager getChatManager() {      return cm;   }         Vector<ChatSocket> vector = new Vector<>();      public void add(ChatSocket cs) {      vector.add(cs);   }      public void publish(ChatSocket cs,String out) {      for (int i = 0; i < vector.size(); i++) {         ChatSocket chatSocket = vector.get(i);         if (!cs.equals(chatSocket)) {            chatSocket.out(out);         }      }   }}

搭建完成后可通过cmd telnet命令测试telnet localhost 12345


----------------------------------------------------------------------------

Java AIO ServerSocket

 public class Main {    public static void main(String[] args){        try {            AsynchronousServerSocketChannel server = AsynchronousServerSocketChannel.open();            server.bind(new InetSocketAddress(8000));            while (true){                /*server.accept(server, new CompletionHandler<AsynchronousSocketChannel, AsynchronousServerSocketChannel>() {                    @Override                    public void completed(AsynchronousSocketChannel result, AsynchronousServerSocketChannel attachment) {                    }                    @Override                    public void failed(Throwable exc, AsynchronousServerSocketChannel attachment) {                    }                });*/                AsynchronousSocketChannel socketChannel = server.accept().get();                new SocketHandler(socketChannel);            }        } catch (IOException | InterruptedException | ExecutionException e) {            e.printStackTrace();        }    }}

public class SocketHandler {    ByteBuffer buffer = ByteBuffer.allocate(1024);    public SocketHandler(AsynchronousSocketChannel channel) {        //服务器监听得到的数据  发布数据可用channel.write        channel.read(buffer, channel, new CompletionHandler<Integer, AsynchronousSocketChannel>() {            @Override            public void completed(Integer result, AsynchronousSocketChannel attachment) {                buffer.flip();                try {                    String msg = new String(buffer.array(),0,buffer.remaining(),"UTF-8");                    System.out.println(msg);                    if (msg.trim().equals("quit")){                        attachment.close();                    }                } catch (IOException e) {                    e.printStackTrace();                }                buffer.clear();                if (result != -1) {                    attachment.read(buffer,attachment,this);                }else {                    System.out.println("连接已断开");                }            }            @Override            public void failed(Throwable exc, AsynchronousSocketChannel attachment) {                System.out.println("读取失败");            }        });    }}

同样用telnet测试


--------------------------------------------------------------

mina框架,基于NIO

进入mina官网:mina.apache.org,下载mina Binaries库,如需查看源代码一并下载Source。新建IEAD项目,新建libs目录,将mina-***-bin.zip中dist和lib的jar文件全部拷贝到项目libs中,然后右键Add as Library,有兴趣可以查看mina-example的示例代码。

简单用法如下:

public class Main {    public static void main(String[] args){        NioSocketAcceptor acceptor = new NioSocketAcceptor();//        acceptor.getFilterChain().addLast("textLineCodec",new ProtocolCodecFilter(new TextLineCodecFactory()));//添加滤镜 API中的滤镜   -->将数据分成一行一行        acceptor.getFilterChain().addLast("StringFilter",new StringFilter());//自定义字符串滤镜        acceptor.setHandler(new SocketHandler());        try {            acceptor.bind(new InetSocketAddress(55555));            System.out.println("Server started at port 55555");        } catch (IOException e) {            e.printStackTrace();        }    }}

//自定义的ProtocolCodecFilterpublic class StringFilter extends IoFilterAdapter {    @Override    public void messageReceived(NextFilter nextFilter, IoSession session, Object message) throws Exception {        IoBuffer buffer = (IoBuffer) message;        String str = new String(buffer.array(),"UTF-8").trim();        super.messageReceived(nextFilter, session, str);//        super.messageReceived(nextFilter, session, message);    }}

public class SocketHandler extends IoHandlerAdapter{    @Override    public void sessionCreated(IoSession session) throws Exception {        super.sessionCreated(session);        System.out.println("create");    }    @Override    public void messageReceived(IoSession session, Object message) throws Exception {        super.messageReceived(session, message);        /*        //无滤镜  --------------telnet 要用 send 命令输入消息!!!!!!!!!!!!        IoBuffer buffer = (IoBuffer) message;        String str = new String(buffer.array(),"UTF-8");        System.out.println(str.trim());*/        //加滤镜之后数据变成一行一行的  ----------telnet 可直接输入消息!!!!!!!!!!        //自定义字符串滤镜也是用下面方法   ----------telnet 要用 send 命令输入消息!!!!!!!!!!!        String line = (String) message;        System.out.println(line);        if (line.equals("quit")){            session.close(true);        }    }}
若要实现聊天功能,在Handler记录每个session的创建与销毁,接收到消息时还需广播给这些session:

    private List<IoSession> allSessions = new ArrayList<>();    @Override    public void sessionCreated(IoSession session) throws Exception {        super.sessionCreated(session);        allSessions.add(session);    }    @Override    public void sessionClosed(IoSession session) throws Exception {        super.sessionClosed(session);        allSessions.remove(session);    }    @Override    public void messageReceived(IoSession session, Object message) throws Exception {        super.messageReceived(session, message);//        for (IoSession ioSession:allSessions){//            ioSession.write(message);//        }        allSessions.stream().filter(ioSession -> !ioSession.equals(session)).forEach(ioSession -> ioSession.write(message));    }

-------------------------------------------------------------

Android客户端

Socket链接最好写在Service里面,这里为方便演示直接放在Activity里。



 import android.os.AsyncTask;import android.os.Bundle;import android.support.v7.app.AppCompatActivity;import android.view.View;import android.widget.Button;import android.widget.EditText;import android.widget.TextView;import android.widget.Toast;import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.IOException;import java.io.InputStreamReader;import java.io.OutputStreamWriter;import java.net.Socket;public class MainActivity extends AppCompatActivity implements View.OnClickListener {    private EditText ip, editText;    private TextView text;    private Button btnConnect, btnSend;        @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        ip = (EditText) findViewById(R.id.etIP);        editText = (EditText) findViewById(R.id.etSend);        text = (TextView) findViewById(R.id.tvChat);        btnConnect = (Button) findViewById(R.id.btnConnect);        btnSend = (Button) findViewById(R.id.btnSend);        btnConnect.setOnClickListener(this);        btnSend.setOnClickListener(this);    }    @Override    public void onClick(View v) {        switch (v.getId()) {            case R.id.btnConnect:                connect();                break;            case R.id.btnSend:                send();                break;        }    }    //TODO-----------------------------------------------------    Socket socket = null;    BufferedWriter writer = null;    BufferedReader reader = null;    public void connect() {        //手机连接本地的地址 真机就是连接wifi的ip 虚拟机10.0.0.2或者其他  比如我的10.0.3.2        final String dstName = ip.getText().toString();        AsyncTask<Void, String, Void> read = new AsyncTask<Void, String, Void>() {            @Override            protected Void doInBackground(Void... params) {                try {                    socket = new Socket(dstName, 12345);                    writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));                    reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));                    publishProgress("@success");                } catch (IOException e) {                    e.printStackTrace();                }                try {                    String line;                    while ((line = reader.readLine()) != null) {                        publishProgress(line);                    }                } catch (IOException e) {                    Toast.makeText(MainActivity.this, "无法建立连接", Toast.LENGTH_SHORT).show();                    e.printStackTrace();                }                return null;            }            @Override            protected void onProgressUpdate(String... values) {                if (values[0].equals("@success")) {                    Toast.makeText(MainActivity.this, "连接成功", Toast.LENGTH_SHORT).show();                }                text.append("别人说:" + values[0] + "\n");                super.onProgressUpdate(values);            }        };        read.execute();    }    public void send() {        try {            text.append("我说:" + editText.getText().toString() + "\n");            writer.write(editText.getText().toString() + "\n");            writer.flush();            editText.setText("");        } catch (IOException e) {            e.printStackTrace();        }    }}


































0 0
原创粉丝点击