Android中Socket的实例分析(一)

  最近学习了Android的socket相关知识,但总觉得很空,便去网上找了个项目学习一下。以下其实都是自己的学习笔记,若有不对之处还望大神指出。
  项目是做一个android实时聊天的客户端,当然你也要求别太高,和QQ比起来差的远呢,但确实可以实现聊天的功能。
  接下来就先把服务端的框架给大家看看。
Android中Socket的实例分析(一)_第1张图片

  这是一个java项目,main函数在MyServerSocket.java中,在main函数中调用ServerListener这个线程。

ServerListener.java

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

import javax.swing.JOptionPane;

public class ServerListener extends Thread {

    @Override
    public void run() {
        //1-65535
        try {
            ServerSocket serverSocket = new ServerSocket(12345);
            while (true) {
                //block
                Socket socket = serverSocket.accept();
                JOptionPane.showMessageDialog(null, "有机器链接到了端口12345");      
                ChatSocket cs = new ChatSocket(socket);
                cs.start();
                ChatManager.getChatManager().add(cs);
            }

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

这里在普及一下ServerSocket,这个同学已经把课本上关于ServerSocket的知识弄下来了,我也学习了,该用的都有了。
转载自lin49940的ServerSocket 用法详解(一)
这里有个知识点很重要,所以特别指出—-创建绑定端口的服务器进程后, 当客户进程的 Socket构造方法返回成功, 表示客户进程的连接请求被加入到服务器进程的请求连接队列中. 虽然客户端成功返回 Socket对象, 但是还没跟服务器进程形成一条通信线路. 必须在服务器进程通过 ServerSocket 的 accept() 方法从请求连接队列中取出连接请求, 并返回一个Socket 对象后, 服务器进程这个Socket 对象才与客户端的 Socket 对象形成一条通信线路.
所以代码中通过该方法获得了一个可以与客户端通信的socket。

ChatSocket.java

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.net.Socket;

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) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    @Override
    public void run() {
        out("你已经链接到本服务器");
        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) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }
}

  在这里,看到通过构造方法,已经将与客户端通信的socket传递给了客户端,由于ChatSocket继承自Thread,所以必须重写run()方法,在run()方法中通过流的方式将socket中的数据读出并且返回一个输入流,然后将数据存储到缓冲区去,之后便一行一行的读,将输入的数据输出到控制台。如果只有你一个客户端的话,本地服务器是已经可以接收并且给你返回信息了。但这肯定不是我们想要的。
ChatManager.java

import java.util.Vector;

public class ChatManager {

    private ChatManager(){}
    private static final ChatManager cm = new ChatManager();
    public static ChatManager getChatManager() {
        return cm;
    }

    Vector<ChatSocket> vector = new Vector<ChatSocket>();

    public void add(ChatSocket cs) {
        vector.add(cs);
    }

    public void publish(ChatSocket cs,String out) {
        for (int i = 0; i < vector.size(); i++) {
            ChatSocket csChatSocket = vector.get(i);
            if (!cs.equals(csChatSocket)) {
                csChatSocket.out(out);
            }
        }
    }
}

  这个类中有二个方法,一个是add()方法,一个是publish()方法,add()方法是将进入服务器的聊天socket都添加到一个集合中去,你在SocketListener中可以看到,只要你尝试连接到给定端口,就会创建一个新的ChatSocket,并且将该ChatSocket加入到集合中,publish()方法是只要不是发送消息的用户,都要输出消息即做到了聊天,当然了这个聊天是没有用户名的,只有自己和别人(可以是很多个别人)。
  到此服务端就完成了,在Eclipse中运行,然后打开网页访问本机的你自己给定的会弹出窗口显示有人连接上了你的端口。你也可以用telnet命令访问并发送消息。

你可能感兴趣的:(android,socket)