• Android中基于TCP协议的网络通信之使用Socket进行通信


    TCP协议被称为一种端到端的协议。这是因为它为两台计算机的连接起到了重要作用:当一台计算机需要与另一台计算机进行接连时,TCP协议会他们之间建立一个连接:用于发送和接收数据的虚拟链路。

    TCP协议负责收集这些信息包,并将其按适当的顺序放好传送,在接收端收到后再将其正确地还原。TCP协议确保了数据包在传送中准确无误。TCP协议使用重发机制:当一个通信实体发送一个消息给另一个通信实体后,需要收到另一个通信实体的确认信息,如果没有收到另一个通信实体的确认信息,则会重发刚才发送的消息。可以通过下面的图例来简单了解TCP协议控制两个通信实体互相通信的过程:


    Java中能接收其他通信实体连接请求的类是ServerSocket,ServerSocket对象用来监听来自客户端的Socket连接,如果没有连接,它将一直处于等待状态。

    根据上面的示意图,可以看出我们至少需要两个计算机设备才能进行通信。一个是服务器端,一个客户端。在这里可能有人会说:那两个人聊QQ、微信的时候两个都是客户端啊。不错,的确两个都是客户端。但是,要知道,这两个客户端都要和腾讯的服务器连接才能通信。好了,下面我们就来用代码来做一个综述。

    首先是服务器端(Java程序,运行于PC):

    public class SimpleServer {
    
    	public static void main(String[] args) throws IOException{
    		ServerSocket ss = new ServerSocket(30000);
    		while (true) {
    			Socket s = ss.accept();
    			OutputStream os = s.getOutputStream();
    			os.write(("我是william的忠实服务器!" + Calendar.getInstance().getTimeInMillis()).getBytes("utf-8"));
    			os.close();
    			s.close();
    		}
    	}
    }
    这里我用的端口号是30000,一般来说我们推荐使用1024以上的端口号,主要是为了避免与其他的应用程序的通用端口发生冲突。

    这里我们用了一个死循环来监听来自客户端的连接信息。这里我们是把当前毫秒时间传给了Socket的outputStream。这里一点需要注意,那就是我用了一个.getBytes("utf-8")。这是因为,我们的服务器端是运行在PC上,一般是Windows主机,当直接使用PrintStream输出字符串时默认使用系统平台的字符串(GBK)编码,但客户端都是Android程序,运行于Linux平台,因为客户端读取网络数据时默认使用UTF-8字符集进行解码,这样就会造成乱码。

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

    下面是客户端程序(Android程序,运行于Android机):

    Handler handler = new Handler(){
    		public void handleMessage(android.os.Message msg) {
    			if (msg.what == 123) {
    				try {
    					Socket socket = new Socket("192.168.1.105", 30000);
    					BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
    					String line = reader.readLine();
    					
    					TextView showTextView = (TextView) findViewById(R.id.activity_simple_client_textview);
    					showTextView.setText("来自服务器的数据:" + line);
    					reader.close();
    					socket.close();
    				} catch (Exception e) {
    					e.printStackTrace();
    				}
    			}
    		};
    	};
    这里只提供了在Handler线程中的关键代码,因为在UI线程的部分非常简单,这里不给出代码,完整代码后面会有接连源码下载。
    在客户端我们使用了IP为192.168.1.105的主机,因为笔者的PC就是这个IP。如果你的电脑你不知道怎么查看IP或是你的IP地址是设置为自动获取IP地址,那么可以使用下图的方法(在开始菜单下输入cmd进入命令提示符窗口):



    进入cmd的方法:



    另外如果你需要修改你的服务器端程序,并且要运行修改后的程序,你可能会遇到这样的一种情况:


    遇到这种情况,不是你的程序修改的时候有问题。而是因为这个时候,你的服务器端程序里写了一个死循环,这个死循环会一直在运行。我们可以通过任务管理器查看到这个进程还在运行着,如下:


    我们只在kill掉这个进程,然后再运行服务器程序,这样就可以了。

    运行程序,如下结果:



    本博客参考资料:《疯狂Android讲义》

    这里是我的程序源码(服务器端和客户端):点击下载源码



  • 相关阅读:
    类和对象
    循环结构(二)
    循环结构(一)
    Java数据类型
    对Java的初识
    函数的作用域、作用域链以及return关键字
    var、fucntion关键字优先级问题
    JavaScript中定义函数的几种方式
    JavaScript变量名与函数名的命名规范
    使用JavaScript分别实现4种样式的九九乘法表(1X1分别在左上、左下、右上、右下)
  • 原文地址:https://www.cnblogs.com/fengju/p/6336148.html
Copyright © 2020-2023  润新知