java socket android_Android:这是一份很详细的Socket使用攻略

089fb79e308b

前言

Socket的使用在 Android网络编程中非常重要

今天我将带大家全面了解 Socket 及 其使用方法

目录

089fb79e308b

示意图

1.网络基础

阅读本文前,请先了解 关于计算机网络基础,如计算机体系结构、TCP、UDP等知识

2. Socket定义

即套接字,是应用层 与 TCP/IP 协议族通信的中间软件抽象层,表现为一个封装了 TCP / IP协议族 的编程接口(API)

089fb79e308b

示意图

Socket不是一种协议,而是一个编程调用接口(API),属于传输层(主要解决数据如何在网络中传输)

即:通过Socket,我们才能在Andorid平台上通过 TCP/IP协议进行开发

对用户来说,只需调用Socket去组织数据,以符合指定的协议,即可通信

成对出现,一对套接字:

Socket ={(IP地址1:PORT端口号),(IP地址2:PORT端口号)}

一个 Socket 实例 唯一代表一个主机上的一个应用程序的通信链路

3. 建立Socket连接过程

089fb79e308b

示意图

4. 原理

Socket的使用类型主要有两种:

流套接字(streamsocket) :基于 TCP协议,采用 流的方式 提供可靠的字节流服务

数据报套接字(datagramsocket):基于 UDP协议,采用 数据报文 提供数据打包发送的服务

具体原理图如下:

089fb79e308b

原理图

5. Socket 与 Http 对比

Socket属于传输层,因为 TCP / IP协议属于传输层,解决的是数据如何在网络中传输的问题

HTTP协议 属于 应用层,解决的是如何包装数据

由于二者不属于同一层面,所以本来是没有可比性的。但随着发展,默认的Http里封装了下面几层的使用,所以才会出现Socket & HTTP协议的对比:(主要是工作方式的不同):

Http:采用 请求—响应 方式。

即建立网络连接后,当 客户端 向 服务器 发送请求后,服务器端才能向客户端返回数据。

可理解为:是客户端有需要才进行通信

Socket:采用 服务器主动发送数据 的方式

即建立网络连接后,服务器可主动发送消息给客户端,而不需要由客户端向服务器发送请求

可理解为:是服务器端有需要才进行通信

6. 使用步骤

Socket可基于TCP或者UDP协议,但TCP更加常用

所以下面的使用步骤 & 实例的Socket将基于TCP协议

// 步骤1:创建客户端 & 服务器的连接

// 创建Socket对象 & 指定服务端的IP及端口号

Socket socket = new Socket("192.168.1.32", 1989);

// 判断客户端和服务器是否连接成功

socket.isConnected());

// 步骤2:客户端 & 服务器 通信

// 通信包括:客户端 接收服务器的数据 & 发送数据 到 服务器

// 步骤1:创建输入流对象InputStream

InputStream is = socket.getInputStream()

// 步骤2:创建输入流读取器对象 并传入输入流对象

// 该对象作用:获取服务器返回的数据

InputStreamReader isr = new InputStreamReader(is);

BufferedReader br = new BufferedReader(isr);

// 步骤3:通过输入流读取器对象 接收服务器发送过来的数据

br.readLine();

// 步骤1:从Socket 获得输出流对象OutputStream

// 该对象作用:发送数据

OutputStream outputStream = socket.getOutputStream();

// 步骤2:写入需要发送的数据到输出流对象中

outputStream.write(("Carson_Ho"+"\n").getBytes("utf-8"));

// 特别注意:数据的结尾加上换行符才可让服务器端的readline()停止阻塞

// 步骤3:发送数据到服务端

outputStream.flush();

// 步骤3:断开客户端 & 服务器 连接

os.close();

// 断开 客户端发送到服务器 的连接,即关闭输出流对象OutputStream

br.close();

// 断开 服务器发送到客户端 的连接,即关闭输入流读取器对象BufferedReader

socket.close();

// 最终关闭整个Socket连接

7. 具体实例

实例 Demo 代码包括:客户端 & 服务器

本文着重讲解客户端,服务器仅采用最简单的写法进行展示

7.1 客户端 实现

步骤1:加入网络权限

步骤2:主布局界面设置

包括创建Socket连接、客户端 & 服务器通信的按钮

android:id="@+id/connect"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:text="connect" />

android:id="@+id/disconnect"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:text="disconnect" />

android:id="@+id/receive_message"

android:layout_width="match_parent"

android:layout_height="wrap_content" />

android:id="@+id/Receive"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:text="Receive from message" />

android:id="@+id/edit"

android:layout_width="match_parent"

android:layout_height="wrap_content" />

android:id="@+id/send"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:text="send"/>

步骤3:创建Socket连接、客户端 & 服务器通信

具体请看注释

MainActivity.java

package scut.carson_ho.socket_carson;

import android.os.Bundle;

import android.os.Handler;

import android.os.Message;

import android.support.v7.app.AppCompatActivity;

import android.view.View;

import android.widget.Button;

import android.widget.EditText;

import android.widget.TextView;

import java.io.BufferedReader;

import java.io.IOException;

import java.io.InputStream;

import java.io.InputStreamReader;

import java.io.OutputStream;

import java.net.Socket;

import java.util.concurrent.ExecutorService;

import java.util.concurrent.Executors;

public class MainActivity extends AppCompatActivity {

/**

* 主 变量

*/

// 主线程Handler

// 用于将从服务器获取的消息显示出来

private Handler mMainHandler;

// Socket变量

private Socket socket;

// 线程池

// 为了方便展示,此处直接采用线程池进行线程管理,而没有一个个开线程

private ExecutorService mThreadPool;

/**

* 接收服务器消息 变量

*/

// 输入流对象

InputStream is;

// 输入流读取器对象

InputStreamReader isr ;

BufferedReader br ;

// 接收服务器发送过来的消息

String response;

/**

* 发送消息到服务器 变量

*/

// 输出流对象

OutputStream outputStream;

/**

* 按钮 变量

*/

// 连接 断开连接 发送数据到服务器 的按钮变量

private Button btnConnect, btnDisconnect, btnSend;

// 显示接收服务器消息 按钮

private TextView Receive,receive_message;

// 输入需要发送的消息 输入框

private EditText mEdit;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

/**

* 初始化操作

*/

// 初始化所有按钮

btnConnect = (Button) findViewById(R.id.connect);

btnDisconnect = (Button) findViewById(R.id.disconnect);

btnSend = (Button) findViewById(R.id.send);

mEdit = (EditText) findViewById(R.id.edit);

receive_message = (TextView) findViewById(R.id.receive_message);

Receive = (Button) findViewById(R.id.Receive);

// 初始化线程池

mThreadPool = Executors.newCachedThreadPool();

// 实例化主线程,用于更新接收过来的消息

mMainHandler = new Handler() {

@Override

public void handleMessage(Message msg) {

switch (msg.what) {

case 0:

receive_message.setText(response);

break;

}

}

};

/**

* 创建客户端 & 服务器的连接

*/

btnConnect.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View v) {

// 利用线程池直接开启一个线程 & 执行该线程

mThreadPool.execute(new Runnable() {

@Override

public void run() {

try {

// 创建Socket对象 & 指定服务端的IP 及 端口号

socket = new Socket("192.168.1.172", 8989);

// 判断客户端和服务器是否连接成功

System.out.println(socket.isConnected());

} catch (IOException e) {

e.printStackTrace();

}

}

});

}

});

/**

* 接收 服务器消息

*/

Receive.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View v) {

// 利用线程池直接开启一个线程 & 执行该线程

mThreadPool.execute(new Runnable() {

@Override

public void run() {

try {

// 步骤1:创建输入流对象InputStream

is = socket.getInputStream();

// 步骤2:创建输入流读取器对象 并传入输入流对象

// 该对象作用:获取服务器返回的数据

isr = new InputStreamReader(is);

br = new BufferedReader(isr);

// 步骤3:通过输入流读取器对象 接收服务器发送过来的数据

response = br.readLine();

// 步骤4:通知主线程,将接收的消息显示到界面

Message msg = Message.obtain();

msg.what = 0;

mMainHandler.sendMessage(msg);

} catch (IOException e) {

e.printStackTrace();

}

}

});

}

});

/**

* 发送消息 给 服务器

*/

btnSend.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View v) {

// 利用线程池直接开启一个线程 & 执行该线程

mThreadPool.execute(new Runnable() {

@Override

public void run() {

try {

// 步骤1:从Socket 获得输出流对象OutputStream

// 该对象作用:发送数据

outputStream = socket.getOutputStream();

// 步骤2:写入需要发送的数据到输出流对象中

outputStream.write((mEdit.getText().toString()+"\n").getBytes("utf-8"));

// 特别注意:数据的结尾加上换行符才可让服务器端的readline()停止阻塞

// 步骤3:发送数据到服务端

outputStream.flush();

} catch (IOException e) {

e.printStackTrace();

}

}

});

}

});

/**

* 断开客户端 & 服务器的连接

*/

btnDisconnect.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View v) {

try {

// 断开 客户端发送到服务器 的连接,即关闭输出流对象OutputStream

outputStream.close();

// 断开 服务器发送到客户端 的连接,即关闭输入流读取器对象BufferedReader

br.close();

// 最终关闭整个Socket连接

socket.close();

// 判断客户端和服务器是否已经断开连接

System.out.println(socket.isConnected());

} catch (IOException e) {

e.printStackTrace();

}

}

});

}

}

7.2 服务器 实现

因本文主要讲解客户端,所以服务器仅仅是为了配合客户端展示;

为了简化服务器使用,此处采用Mina框架

服务器代码请在eclipse平台运行

按照我的步骤一步步实现就可以无脑运行了

步骤1:导入Mina包

089fb79e308b

示意图

步骤2:创建服务器线程

TestHandler.java

package mina;

// 导入包

public class TestHandler extends IoHandlerAdapter {

@Override

public void exceptionCaught(IoSession session, Throwable cause) throws Exception {

System.out.println("exceptionCaught: " + cause);

}

@Override

public void messageReceived(IoSession session, Object message) throws Exception {

System.out.println("recieve : " + (String) message);

session.write("hello I am server");

}

@Override

public void messageSent(IoSession session, Object message) throws Exception {

}

@Override

public void sessionClosed(IoSession session) throws Exception {

System.out.println("sessionClosed");

}

@Override

public void sessionOpened(IoSession session) throws Exception {

System.out.println("sessionOpen");

}

@Override

public void sessionIdle(IoSession session, IdleStatus status) throws Exception {

}

}

步骤3:创建服务器主代码

TestHandler.java

package mina;

import java.io.IOException;

import java.net.InetSocketAddress;

import org.apache.mina.filter.codec.ProtocolCodecFilter;

import org.apache.mina.filter.codec.textline.TextLineCodecFactory;

import org.apache.mina.transport.socket.nio.NioSocketAcceptor;

public class TestServer {

public static void main(String[] args) {

NioSocketAcceptor acceptor = null;

try {

acceptor = new NioSocketAcceptor();

acceptor.setHandler(new TestHandler());

acceptor.getFilterChain().addLast("mFilter", new ProtocolCodecFilter(new TextLineCodecFactory()));

acceptor.setReuseAddress(true);

acceptor.bind(new InetSocketAddress(8989));

} catch (Exception e) {

e.printStackTrace();

}

}

}

至此,客户端 & 服务器的代码均实现完毕。

7.3 测试结果

点击 Connect按钮: 连接成功

089fb79e308b

示意图

输入发送的消息,点击 Send 按钮发送

089fb79e308b

示意图

服务器接收到客户端发送的消息

089fb79e308b

示意图

点击 Receive From Message按钮,客户端 读取 服务器返回的消息

089fb79e308b

示意图

点击 DisConnect按钮,断开 客户端 & 服务器的连接

089fb79e308b

客户端示意图

089fb79e308b

服务器示意图

7.4 源码地址

8. 总结

相信大家已经非常了解关于Socket的使用

下面我将继续对 Android 的网络编程进行讲解,感兴趣的同学可以继续关注本人运营的Wechat Public Account:

请点赞!因为你的鼓励是我写作的最大动力!

不定期分享关于安卓开发的干货,追求短、平、快,但却不缺深度。

089fb79e308b

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/442937.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

内构函数java_Android JNI参数传递

Java中调用native函数传递的参数是Java数据类型,到了JNI层需进行数据类型转换,基本数据类型是在前面加个j,如int——>jint,应用数据类型除了基本数据类型的数据、Class、String和Throwable外,其余所有Java对象的数据…

java 垃圾回收机制_Java的垃圾回收机制

前言在C语言中, 程序员必须小心谨慎的处理每一项内存分配, 且内存使用完后必须手动释放曾经占用的内存空间。当内存释放不够完全时, 即存在分配但永不释放的内存块, 就会引起"内存泄漏"问题。而在Java语言中, 它给了程序员一个美好的承诺: 程序员无需管理内存, 因为J…

java闹钟程序声音_跪求高手帮忙写一个JAVA手机闹钟程序 实现添加铃声和设置多闹钟...

展开全部import java.util.*;import java.awt.*;import java.applet.*;import java.text.*;public class AlarmClock extends Applet implements Runnable{Thread timernull; //创建线程timerImage clockp,gif1,gif2,clock6,clock7; //clockp:闹钟的外壳,闹铃和e68a…

摩托罗拉ex232java_摩托罗拉ex232r如何刷机?摩托罗拉ex232r评测

导语:随着 高科 技产业的发展,手机作为一个深受影响的产业,其竞争的激烈程度也是不言而喻的。市场好比战场,而为了在这个手机战场中赢 得胜 利,不论国内或者是国外的各大厂商也都全身心的投入到新技术的开发和新产品的…

JAVA捕捉输入格式异常_Java学习(四).异常处理

异常处理任何一个软件或程序都可能在运行的过程中出现故障,问题的关键是故障出现以后如何处理?谁来处理?怎样处理?处理后系统能否恢复正常的运行?本章在介绍Java处理这类问题基本方法的基础上,讨论包含异常…

php去除html属性,PHP如何去掉所有HTML标签?

PHP如何去掉所有HTML标签?在PHP中可以使用“strip_tags()”函数将字符串中的所有HTML标签去除,该函数用于从字符串中去除HTML和 PHP标记,其语法是“strip_tags(str)”,其参数str表示要进行操作的字符串,返回值为处理后…

php获取本机root,通过PHP执行root命令

慕村225694在尝试之前&#xff0c;请阅读整个文章&#xff0c;然后进行选择。使用二进制包装器(带有suid位)的解决方案1)创建一个脚本(最好是.sh)&#xff0c;其中包含要作为root用户运行的脚本。# cat > php_shell.sh < wrapper.c < #include #include int mai…

java寂静岭 攻略,GBA版《寂静岭》HARRY篇图文流程攻略

“Play Novel: Silent Hill”是KONAMI于2001年3月21日在GBA上推出的一款文字冒险游戏&#xff0c;剧情内容取自同社的恐怖冒险游戏——Silent Hill(《寂静岭》)。游戏基本上是纯粹的文字冒险游戏&#xff0c;过程中穿插着几段动画CG作为过场&#xff0c;游戏中绝大部分的图片和…

实验一熟悉matlab环境,数字信号处理报告实验一:熟悉MATLAB环境.doc

数字信号处理报告实验一&#xff1a;熟悉MATLAB环境.doc实验一熟悉MATLAB环境一 实验目的1. 熟悉MATLAB的主要操作命令。2. 学会简单的矩阵输入和数据读写。3. 掌握简单的绘图命令。4. 用MATLAB编程并学会创建函数。5. 观察离散系统的频率响应。二 实验内容2.用MATLAB实现下列序…

微擎cloud.mod.php,微擎“could not resolve ”、“could not resolve host”系列问题处理办法...

今天一个用户跟我说模块安装出现”could not resolve host:update.we10d.cn“报错&#xff0c;昨天在整理最近十个月用户搜索关键词排行的时候也发现”could not resolve host“、”could not resolve“还是占据不小的比例的。其实这类报错的处理方法大致相同&#xff0c;都是/…

php类如何变为静态调用,PHP类中静态方法如何调用非静态方法?_后端开发

php如何将字符串转成json_后端开发php将字符串转成json的方法是&#xff1a;可以通过json_encode()函数来实现。json_encode()函数用于对变量进行JSON编码&#xff0c;该函数如果执行成功&#xff0c;则返回JSON数据&#xff0c;反之则返回FALSE。PHP类中静态方法调用非静态方法…

PHP的注释标记是什么,html的注释标记是什么

html的注释标记是“”&#xff0c;用来在源文档中插入注释&#xff0c;注释的内容不会被显示在浏览器页面上。只有在文本编辑器中&#xff0c;或浏览器的“查看源代码”选项打开文档时&#xff0c;才能看到注释。本教程操作环境&#xff1a;windows7系统、HTML5版、Dell G3电脑…

linux 监控命令行输入,监控 Linux 容器性能的命令行神器

ctop是一个新的基于命令行的工具&#xff0c;它可用于在容器层级监控进程。容器通过利用控制器组(cgroup)的资源管理功能&#xff0c;提供了操作系统层级的虚拟化环境。该工具从cgroup收集与内存、CPU、块输入输出的相关数据&#xff0c;以及拥有者、开机时间等元数据&#xff…

linux子系统停止运行,linux 系统部署spring boot 退出连接端后项目停止运行问题

准备&#xff1a;Linux系统、jar包、一个启动项目文件(starup.sh)文件名自定义1、首先需要编辑starup.sh文件&#xff0c;这里我也是从网上找了一个比较好的内容如下&#xff1a;#!/bin/bash#这里可替换为你自己的执行程序&#xff0c;其他代码无需更改APP_NAMEkaRen.jar#使用说…

linux程序mktime无权限,linux中mktime算法解析

Linux源码中的mktime算法解析我们知道&#xff0c;从CMOS中读出来的系统时间并不是time_t类型&#xff0c;而是类似于struct tm那样&#xff0c;年月日时分秒是分开存储的。那么&#xff0c;要把它转化为系统便于处理的time_t类型&#xff0c;就需要算法进行转换。我们都知道我…

linux 无线网卡连接网络连接不上去,【已解决】Ubuntu 10.04 无线网卡 无法连接

----------------------------------搬家声明------------------------------------------------------------------------搬家声明--------------------------------------【已解决】Ubuntu 10.04 无线网卡 无法连接【问题】新装的Ubuntu 10.04&#xff0c;其他一切正常&#…

Linux 软件包管理器的目的是什么,Linux软件包的管理--RPM包管理器

在Linux中如何安装、升级、卸载软件&#xff0c;是我们日常运维中重要的组成部分。接下来一CentOS6系统为例&#xff0c;讲解如何使用 RPM 包管理器&#xff0c;yum包管理器以及源码的方式来管理我们的软件包。一、相关的背景知识许多程序的源程序&#xff0c;例如使用C语言编写…

嵌入式linux mongodb,小白在Ubuntu安装mongoDB与mongo-c-driver

目的&#xff1a;本人从事嵌入式软件&#xff0c;项目中需要使用MongoDB&#xff0c;最终需要熟悉c-driver的API&#xff0c;小白在搭建环境有些浪费时间&#xff0c;故写这文章让与我同样状态的开发人员学习学习。在Ubuntu上的安装mongodb方法一&#xff1a;sudo apt-get ins…

湘潭大学-软件工程-选择判断题复习

说明 期末考试单选题和判断题占30分&#xff0c;单选20&#xff0c;判断10分 单选题 选错误的 B依靠松散组合的互联网大众是无法开发出高质量软件产品的 D、所有命名都应尽量使用缩写 C、采用团队的组织方式 D、软件需求一旦确定就不允许变化 以下哪一项是通过运行程序…

c语言运算符ppt,C语言知识学习运算符.ppt

C语言知识学习运算符.ppt 第三章,C语言运算符,回顾,变量和常量的含义 熟悉基本数据类型 - int、char、float 和 double 使用算术运算符 理解类型转换 熟练使用 scanf 和 printf 函数,课程目标,算术运算符 增量运算符 逻辑运算符 关系运算符 按位运算符 C的特殊运算符 --“” “…