1 Socket 简介

​ Socket(套接字)是应用层与 TCP/IP 协议通信的中间软件抽象层,它是一组接口,用户只需面向 Socket 编程,即可实现跨设备(网络)通讯。

​ Socket 是 java 里的东西,不是 Android 特有的,使用 Socket 需要导入的类如下。

java.net.ServerSocket
java.net.Socket

​ (1)服务端主要接口调用

// 获取 socket
mServerSocket = new ServerSocket(port)
// port 为端口号,取值:0~65535间的整数,前1024个端口号为固定端口,一般不提供给程序员使用,之后为注册端口,为避免端口冲突,建议 port 值取大点
mSocket = mServerSocket.accept() //调用此方法会阻塞线程,建议在子线程中执行 // 读取对端数据
in = mSocket.getInputStream()
byte[] bt = new byte[50]
in.read(bt) // 向对端发送数据
out = new PrintWriter(mSocket.getOutputStream())
out.print(content)
out.flush()

​ (2)客户端主要接口调用

// 获取 socket
mSocket = new Socket(ip, port) //调用此方法会阻塞线程,建议在子线程中执行
// ip 为服务端设备 ip 地址
// port 为端口号,取值:0~65535间的整数,前1024个端口号为固定端口,一般不提供给程序员使用,之后为注册端口,为避免端口冲突,建议 port 值取大点 // 读取对端数据
in = mSocket.getInputStream()
byte[] bt = new byte[50]
in.read(bt) // 向对端发送数据
out = new PrintWriter(mSocket.getOutputStream())
out.print(content)
out.flush()

​ 本文全部代码见→使用Socket实现跨设备通讯

2 项目结构

​ 注意:2个设备必须在局域网中(连同一个wifi )

3 服务端(socket_S)

​ Server.java

package com.zhyan8.socket_s;

import android.os.Handler;
import android.os.Message;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket; public class Server{
private ServerSocket mServerSocket;
private Socket mSocket;
private Handler mHandler;
private InputStream in;
private PrintWriter out;
private Object lock = new Object(); public Server(Handler handler, int port){
mHandler = handler;
try {
mServerSocket = new ServerSocket(port);
} catch (IOException e) {
e.printStackTrace();
}
} public void connect() {
new Thread() {
@Override
public void run() {
try {
synchronized (lock) {
if (mSocket!=null) {
return;
}
mSocket = mServerSocket.accept();
in = mSocket.getInputStream();
out = new PrintWriter(mSocket.getOutputStream());
}
} catch (IOException e) {
e.printStackTrace();
}
}
}.start();
} public void begin_listen() {
while (mSocket==null) {
connect();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
new Thread() {
@Override
public void run() {
try {
while (!mSocket.isClosed()) {
byte[] bt = new byte[50];
in.read(bt);
String content = new String (bt, "UTF-8" );
if (content!=null && !content.equals("")) {
Message msg = new Message();
msg.obj = content;
mHandler.sendMessage(msg);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}.start();
} public void send_msg(final String content) {
new Thread() {
@Override
public void run() {
out.print(content);
out.flush ();
}
}.start();
}
}

​ MainActivity.java

package com.zhyan8.socket_s;

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; public class MainActivity extends AppCompatActivity {
private Server mServer;
private EditText et_msg;
private Button btn_send;
private TextView tv_msg; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
} private void init() {
et_msg = (EditText) findViewById(R.id.et_msg);
btn_send = (Button) findViewById(R.id.btn_send);
tv_msg = (TextView) findViewById(R.id.tv_msg);
btn_send.setOnClickListener(cl);
mServer = new Server(mHandler, 1111);
mServer.begin_listen();
} private View.OnClickListener cl = new View.OnClickListener() {
@Override
public void onClick(View v) {
String content = et_msg.getText().toString().trim();
if (content!=null && !content.equals("")) {
mServer.send_msg(content);
}
}
}; private Handler mHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
String content = (String) msg.obj;
tv_msg.setText(content);
}
};
}

​ activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:orientation="vertical"
tools:context="com.zhyan8.socket_s.MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="100dp"
android:orientation="horizontal"
android:gravity="center_vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="接收的消息:"
android:textSize="20sp"
android:gravity="center_vertical"/>
<TextView
android:id="@+id/tv_msg"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textSize="20sp"
android:gravity="center_vertical"/>
</LinearLayout> <EditText
android:id="@+id/et_msg"
android:layout_width="match_parent"
android:layout_height="100dp"
android:textSize="30sp"
android:background="#ffcc66"/> <Button
android:id="@+id/btn_send"
android:layout_width="match_parent"
android:layout_height="80dp"
android:text="发送"
android:textSize="30sp"
android:layout_marginTop="30dp"/>
</LinearLayout>

​ 界面如下:

​ 在 AndroidManifest.xml 文件的 manifest 标签下(与 application 同级)添加如下权限:

<uses-permission android:name="android.permission.INTERNET" />

4 客户端(socket_C)

​ Client.java

package com.zhyan8.socket_c;

import android.os.Handler;
import android.os.Message; import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.net.Socket; public class Client{
private Socket mSocket;
private Handler mHandler;
private InputStream in;
private PrintWriter out;
private String ip;
private int port;
private Object lock = new Object(); Client(Handler handler, String ip, int port) {
mHandler = handler;
this.ip = ip;
this.port = port;
} private void connect() {
new Thread() {
@Override
public void run() {
try {
synchronized (lock) {
if (mSocket!=null) {
return;
}
mSocket = new Socket(ip, port);
in = mSocket.getInputStream();
out = new PrintWriter(mSocket.getOutputStream());
}
} catch (IOException e) {
e.printStackTrace();
}
}
}.start();
} public void begin_listen() {
while (mSocket==null) {
connect();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
new Thread() {
@Override
public void run() {
try {
while (!mSocket.isClosed()){
byte[] bt = new byte[50];
in.read(bt);
String content = new String (bt, "UTF-8" );
if (content!=null && !content.equals("")) {
Message msg = new Message();
msg.obj = content;
mHandler.sendMessage(msg);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}.start();
} public void send_msg(final String content) {
new Thread() {
@Override
public void run() {
out.print(content);
out.flush();
}
}.start();
}
}

​ MainActivity.java

package com.zhyan8.socket_c;

import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView; public class MainActivity extends AppCompatActivity {
private Client mClient;
private EditText et_msg;
private Button btn_send;
private TextView tv_msg; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
} private void init() {
et_msg = (EditText) findViewById(R.id.et_msg);
btn_send = (Button) findViewById(R.id.btn_send);
tv_msg = (TextView) findViewById(R.id.tv_msg);
btn_send.setOnClickListener(cl);
mClient = new Client(mHandler, "192.168.0.104", 1111);
mClient.begin_listen();
} private View.OnClickListener cl = new View.OnClickListener() {
@Override
public void onClick(View v) {
String content = et_msg.getText().toString().trim();
if (content!=null && !content.equals("")) {
mClient.send_msg(content);
}
}
}; private Handler mHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
String content = (String) msg.obj;
tv_msg.setText(content);
}
};
}

​ activity_main.xml 同第3节。

​ 在 AndroidManifest.xml 文件的 manifest 标签下(与 application 同级)添加如下权限:

<uses-permission android:name="android.permission.INTERNET" />

5 效果展示

​ 客户端:

​ 服务端:

​ 声明:本文转自【Android】使用Socket实现跨设备通讯

【Android】使用Socket实现跨设备通讯的更多相关文章

  1. AllJoyn+Android开发案例-android跨设备调用方法

    AllJoyn+Android开发案例-android跨设备调用方法 项目须要涉及AllJoyn开源物联网框架.前面主要了解了一些AllJoyn主要的概念.像总线,总线附件,总线对象,总线接口这种概念 ...

  2. Android 通过Socket 和服务器通讯

    Extends:(http://www.cnblogs.com/likwo/p/3641135.html) Android 通过Socket 和服务器通讯,是一种比较常用的通讯方式,时间比较紧,说下大 ...

  3. android 跨进程通讯 AIDL

    跨进程如何通讯?两个进程无法直接通讯,通过Android系统底层间接通讯.基于service的aidl实现跨进程通讯. 什么叫AIDL? Android interface definition la ...

  4. android 史上最简单易懂的跨进程通讯(Messenger)!

    不需要AIDL也不需要复杂的ContentProvider,也不需要SharedPreferences或者共享存储文件! 只需要简单易懂的Messenger,它也称为信使,通过它可以在不同进程中传递m ...

  5. Android为TV端助力 史上最简单易懂的跨进程通讯(Messenger)!

    不需要AIDL也不需要复杂的ContentProvider,也不需要SharedPreferences或者共享存储文件! 只需要简单易懂的Messenger,它也称为信使,通过它可以在不同进程中传递m ...

  6. Android 基于Socket的聊天应用(二)

    很久没写BLOG了,之前在写Android聊天室的时候答应过要写一个客户(好友)之间的聊天demo,Android 基于Socket的聊天室已经实现了通过Socket广播形式的通信功能. 以下是我写的 ...

  7. AppCompat v21 — Android 5.0之前版本设备的Material Design实现

    博客原文地址:http://android-developers.blogspot.com/2014/10/appcompat-v21-material-design-for-pre.html,要想打 ...

  8. [置顶] Xamarin android中使用signalr实现即时通讯

    前面几天也写了一些signalr的例子,不过都是在Web端,今天我就来实践一下如何在xamarin android中使用signalr,刚好工作中也用到了这个,也算是总结一下学到的东西吧,希望能帮助你 ...

  9. 以面向对象的思维,搭建Android与多ble蓝牙设备并发通讯小框架

    Android连接多蓝牙设备.蓝牙与多设备连接.蓝牙ble多设备并发操作.Android连接不了.Android ble开发框架.Android 连接蓝牙总结 前言 小白请绕道百度,本文适合有一定An ...

  10. IOT设备通讯,MQTT物联网协议,MQTTnet

    一.IOT设备的特性 硬件能力差(存储能力基本只有几MB,CPU频率低连使用HTTP请求都很奢侈) 系统千差万别(Brillo,mbedOS,RIOT等) 如使用电池供电,电量消耗敏感 如果是小设备, ...

随机推荐

  1. Mybatis @Insert插入数据返回自增的主键id

    mapper层 @Insert("insert into t_user (username,password,valid,create_time) values (#{username},# ...

  2. SQLServer备份恢复的总结-同名恢复与异名恢复

    SQLServer备份恢复的总结 前言 GUI 搞一把. 命令行太多了也没人看 自己还能省点心 备份 备份数据库建议一定要选择: 备份选项中的 压缩->压缩备份 历史经验一个7.6G的数据库能够 ...

  3. [转帖]How fast are Unix domain sockets?

    https://blog.myhro.info/2017/01/how-fast-are-unix-domain-sockets Jan 3, 2017 • Tiago Ilieve Warning: ...

  4. [转帖]TiDB 配置参数修改与系统变量修改步骤

    https://tidb.net/blog/bda86911   注意事项1:tidb-test 为集群名称   注意事项2:参数修改前与修改后备份.tiup目录   注意事项3:通过 tiup cl ...

  5. [转帖]学习如何编写 Shell 脚本(基础篇)

    https://juejin.cn/post/6930013333454061575 前言 如果仅仅会 Linux 一些命令,其实已经可以让你在平时的工作中游刃有余了.但如果你还会编写 Shell 脚 ...

  6. [转帖]Postmark - 存储性能测试工具

    1. 引言 Postmark是由著名的NAS提供商NetApp开发,用来测试其产品的后端存储性能. Postmark主要用于测试文件系统在邮件系统或电子商务系统中性能,这类应用的特点是:需要频繁.大量 ...

  7. 部署于K8S集群上面应用性能影响点推测

    前言 本人2017年第一次接触K8S. 中间断断续续学习K8S相关的内容. 但是最近一年,几乎没太有学习. 因为之前学习了四五年, 一直以为产品马上要用 结果一直被浇冷水. 去年开始学乖了. 不这么搞 ...

  8. echarts设置单位的偏移

    echarts 可以设置的echarts单位的偏移位置吗? 之前是知道echarts的X和Y是可以设置单位的. 但是设置单位的位置一直不好调整. 现在有时间,我们会回答一下上面标题的问题? echar ...

  9. React中兄弟组件通信和组件跨级传递Context的使用

    React兄弟组件之间的通信 Child2组件需要去更改Child1组件中的数据. 因为Child1和Child2是兄弟组件 所以数据和事件都放在最进的父级组件中去 兄弟组件通信的简单使用 impor ...

  10. 【JS 逆向百例】某音 X-Bogus 逆向分析,JSVMP 纯算法还原

    声明 本文章中所有内容仅供学习交流使用,不用于其他任何目的,不提供完整代码,抓包内容.敏感网址.数据接口等均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关! 本文章未经许 ...