在Android上使用Socket

原文地址:http://www.cnblogs.com/kross/p/3621952.html

 

考虑到以后可能要用到这方面的知识,就来写个Demo尝试下,其实以前学过,但不记得了……(用不到的东西各种不记得啊)

直接进入正题吧,在Android上使用Socket实际上跟在Java中使用差不多,只要注意下在Manifest中加网络权限就好了(我原来经常犯这个错误),另外网络请求不能再主线程里,基本就OK了。

そして,先写一个服务器的小程序吧。就直接使用Java写就好了,灰常的简单,随便写写。

/**
 * 测试服务器
 * */
public class TestServer {

    public static void main(String[] args) throws IOException {
        
        ServerSocket ss = new ServerSocket(5417);
        
        Socket client = null;
        
        while (true) {
            System.out.println("waiting for...");
            client = ss.accept();
            BufferedReader br = new BufferedReader(new InputStreamReader(client.getInputStream()));
            System.out.println(br.readLine());
        }
    }
}

然后我的构想是,手机上有一个输入框,一个按钮,用户可以按按钮,把输入框里的内容发送到服务器上。一开始我写了一个很混乱的demo,为了更加方便使用,就把Socket的封装了一下,就叫SocketManager吧,代码如下:

/**
 * SocketManager,简单的封装了一下
 * @author Kross(krossford@foxmail.com)
 * @date 2014-3-24 21:39:48
 * */
public class SocketManager {
    
    private Socket client = null;
    
    //服务器的IP地址
    private String ip = "113.251.172.30";
    
    //监听的端口号
    private int port = 5417;
    
    /**
     * 获取一个实例
     * */
    public static SocketManager newInstance() throws UnknownHostException, IOException {
        return new SocketManager();
    }
    
    private SocketManager() throws UnknownHostException, IOException {
        client = new Socket(ip, port);
    }
    
    /**
     * 发送一条消息
     * @param msg 消息内容
     * */
    public void sendMessage(String msg) throws IOException {
        PrintWriter printWriter = new PrintWriter(client.getOutputStream());
        printWriter.print(msg);
        printWriter.flush();
        printWriter.close();    //一定要关闭输出流,要不然消息无法送达到服务器
    }
}

几个要点:

1.IP地址就写Java程序锁运行的机器的公网地址,cmd->ipconfig就可以查到。

2.端口号请和服务器那个保持一致,都不在一个管道里怎么通信哇。

3.我使用了静态工厂方法,每次都要重新new一个SocketManager,因为我发现Socket这个类只能用一次,close之后再发送便没用了。

4.服务器要收到信息,必须要客户端的东西close了,输出流close也好,socket.close也好,总之要close,服务器才能确切的收到。

然后,我写了一个线程来执行这个Socket,因为不能在主线程跑嘛,我想了很久,可不可以让这个线程一直执行着,然后只要调用下这个线程的sendMessage方法,就可以发送了,这样就只需要new一个线程就行了,但是我想了好久,都想不通,貌似不能那样,线程要么没有,有的话就会一股脑的执行它的run()方法,想要长时间持有它?在run里面加个while(true)?那怎么做到调用它的共有方法呢?总之,我没有想到用只需要new一个线程就可以发N个请求的办法,貌似需要使用到Service来实现了。

/**
 * 发起请求的线程
 * @author Kross(krossford@foxmail.com)
 * @date 2014-3-24 21:40:21
 * */
public class SocketThread implements Runnable {
    
    private String message;
    
    public SocketThread(String msg) {
        message = msg;
    }
    
    @Override
    public void run() {
        try {
            SocketManager.newInstance().sendMessage(message);
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

这里倒没什么好说的。接下来我们就直接在MainActivity里面准备好控件,监听器,然后就OK了,大致的看下代码吧。

public class MainActivity extends Activity {
    
    private EditText etInput = null;
    private Button bSend = null;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        Log.i("MainActivity", Thread.currentThread().getName());
        
        etInput = (EditText)findViewById(R.id.et_input);
        bSend = (Button)findViewById(R.id.b_send);
        
        bSend.setOnClickListener(new SendButtonListener());
        
    }
    
    class SendButtonListener implements OnClickListener {

        @Override
        public void onClick(View v) {
            String msg = etInput.getEditableText().toString().trim();
            new Thread(new SocketThread(msg)).start();
            etInput.setText("");
        }
    }
}

OK,代码就是这样了,来看下最终的运行效果吧。

先启动Java的服务器程序,启动后结果是这样的:

然后我们运行手机上的程序,发送一条消息:

再来看服务器端的程序:

看上去一切正常,再来一发!

再看看服务器的程序:

OK,看来是没有问题了。

 

服务器如何向Socket返回信息暂时还没有去实验,留着明天来搞吧……

 

原文地址:http://www.cnblogs.com/kross/p/3621952.html

新浪微博:http://weibo.com/KrossFord

posted @ 2014-03-24 22:01  krosshuang  阅读(2941)  评论(0编辑  收藏  举报