zoukankan      html  css  js  c++  java
  • 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讲义》

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



  • 相关阅读:
    [译文] 实体与值对象到底是不是一回事?
    实现 WebApi 自托管服务宿主于 WinForms 及其交互
    [译文] C# 8 已成旧闻, 向前, 抵达 C# 9!
    [译文] 为什么你在 C# 里总是应该使用 "var" 关键字
    通过设置iis在局域网中访问网页
    windows 10 安装使用kafka
    ASP.NET Core 2.1 中的 HttpClientFactory (Part 4) 整合Polly实现瞬时故障处理
    ASP.NET Core 2.1 中的 HttpClientFactory (Part 3) 使用Handler实现传出请求中间件
    ASP.NET Core 2.1 中的 HttpClientFactory (Part 2) 定义命名化和类型化的客户端
    Asp.net Core 2.0 OpenId Connect Handler缺失Claims?
  • 原文地址:https://www.cnblogs.com/fengju/p/6336148.html
Copyright © 2011-2022 走看看