一.说明

前文介绍了基于安卓客户端的开发,在此基础上,进行少许改动即可开发出一款基于TCP的安卓服务器,理论知识请参见笔者上一篇博文,下面直接实践操作。

二.权限申明

     <!--允许应用程序改变网络状态-->
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/> <!--允许应用程序改变WIFI连接状态-->
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/> <!--允许应用程序访问有关的网络信息-->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> <!--允许应用程序访问WIFI网卡的网络信息-->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/> <!--允许应用程序完全使用网络-->
<uses-permission android:name="android.permission.INTERNET"/>

三.布局文件

 <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp">
<TextView
android:id="@+id/LocalIPTextView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="本机IP:"
android:textSize="25dp"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginBottom="10dp">
>
<EditText
android:id="@+id/MessagetoSendEditText"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="3"
android:text="Data from Server"/>
<Button
android:id="@+id/SendButton"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="发送"/>
</LinearLayout> <LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp" android:layout_marginBottom="10dp">
<TextView
android:id="@+id/DisplayTextView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="25dp"/>
</LinearLayout> </LinearLayout>

四.具体实现代码

 package com.example.john.androidsockettest;

 import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
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.InputStreamReader;
import java.io.OutputStream;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.util.Enumeration; public class MainActivity extends AppCompatActivity { //线程及套接字定义
public Socket socket = null;
public ServerSocket serverSocket = null;
private AcceptThread acceptThread = null;
private ReceiveThread receiveThread = null;
private SendThread sendThread = null;
//Handler中的消息类型
public static final int DEBUG = 0x00;
public static final int RECEIVEDATAFROMCLIENT = 0x01;
public static final int SENDDATATOCLIENT = 0x02;
//控件
private TextView localIPTextView;
private EditText messagetoSendEditText;
private Button sendButton;
private TextView displayTextView;
//变量定义
String messagetoSend=""; public Handler myHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
if (msg.what == RECEIVEDATAFROMCLIENT) {
Bundle bundle = msg.getData();
displayTextView.append("Client:"+bundle.getString("string1")+"\n");
}
else if (msg.what == DEBUG) {
Bundle bundle = msg.getData();
displayTextView.append("Debug:"+bundle.getString("string1")+"\n");
}
else if (msg.what == SENDDATATOCLIENT) {
Bundle bundle = msg.getData();
displayTextView.append("Server:"+bundle.getString("string1")+"\n");
}
} };
//子线程更新UI
public void SendMessagetoHandler(final int messageType , String string1toHandler){
Message msg = new Message();
msg.what = messageType; //消息类型
Bundle bundle = new Bundle();
bundle.clear();
bundle.putString("string1", string1toHandler); //向bundle中添加字符串
msg.setData(bundle);
myHandler.sendMessage(msg);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//控件对象获取
localIPTextView = (TextView)findViewById(R.id.LocalIPTextView);
messagetoSendEditText = (EditText)findViewById(R.id.MessagetoSendEditText);
sendButton = (Button)findViewById(R.id.SendButton);
displayTextView = (TextView)findViewById(R.id.DisplayTextView);
//服务器IP获取显示
localIPTextView.setText("本机IP:"+getIPAddress(this));
//开启接受线程
acceptThread = new AcceptThread();
acceptThread.start();
sendButton.setOnClickListener(new View.OnClickListener() { @Override
public void onClick(View v) {
messagetoSend = messagetoSendEditText.getText().toString();
//使用连接成功后得到的socket构造发送线程,每点击一次send按钮触发一次发送线程
sendThread = new SendThread(socket);
sendThread.start();
}
}); }
//***** 接受线程 *****
class AcceptThread extends Thread{
@Override
public void run() {
try{
serverSocket = new ServerSocket(8086);
socket = serverSocket.accept();
}catch (IOException e){
e.printStackTrace();
}
SendMessagetoHandler(DEBUG,"客户端连接成功!");
//构造并开启接收线程
receiveThread = new ReceiveThread(socket);
receiveThread.start();
}
}
//******** 接收线程 **********
class ReceiveThread extends Thread{ private Socket mSocket;
//接收线程的构造函数,由接受线程传入套接字
public ReceiveThread(Socket socket){mSocket = socket;}
@Override
public void run() {
while(true){ //连接成功后将一直运行
try {
BufferedReader bufferedReader;
String line = null;
String readBuffer="";
bufferedReader = new BufferedReader(new InputStreamReader(mSocket.getInputStream())); while ((line = bufferedReader.readLine()) != null) {
readBuffer = line + readBuffer;
SendMessagetoHandler(RECEIVEDATAFROMCLIENT,readBuffer);
readBuffer = "";
} }catch (IOException e) {
e.printStackTrace();
//更新UI:显示发送错误信息
SendMessagetoHandler(DEBUG,"接收失败!");
return;
}
}
}
}
//******** 发送线程 **********
class SendThread extends Thread{
private Socket mSocket;
//发送线程的构造函数,由接受线程传入套接字
public SendThread(Socket socket) {mSocket = socket;} @Override
public void run() {
try{
OutputStream outputStream = mSocket.getOutputStream();
//向服务器发送信息
outputStream.write(messagetoSend.getBytes("gbk"));
outputStream.flush();
//更新UI:显示发送出的数据
SendMessagetoHandler(SENDDATATOCLIENT,messagetoSend);
}catch (IOException e) {
e.printStackTrace();
//更新UI:显示发送错误信息
SendMessagetoHandler(DEBUG,"发送失败!");
return;
}
}
}
//***** 获取本机的ip地址
private String getlocalip(){
WifiManager wifiManager = (WifiManager)this.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
WifiInfo wifiInfo = wifiManager.getConnectionInfo();
int ipAddress = wifiInfo.getIpAddress();
// Log.d(Tag, "int ip "+ipAddress);
if(ipAddress==0)return null;
return ((ipAddress & 0xff)+"."+(ipAddress>>8 & 0xff)+"."
+(ipAddress>>16 & 0xff)+"."+(ipAddress>>24 & 0xff));
} public static String getIPAddress(Context context) {
NetworkInfo info = ((ConnectivityManager) context
.getSystemService(Context.CONNECTIVITY_SERVICE)).getActiveNetworkInfo();
if (info != null && info.isConnected()) {
if (info.getType() == ConnectivityManager.TYPE_MOBILE) {//当前使用2G/3G/4G网络
try {
//Enumeration<NetworkInterface> en=NetworkInterface.getNetworkInterfaces();
for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements(); ) {
NetworkInterface intf = en.nextElement();
for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements(); ) {
InetAddress inetAddress = enumIpAddr.nextElement();
if (!inetAddress.isLoopbackAddress() && inetAddress instanceof Inet4Address) {
return inetAddress.getHostAddress();
}
}
}
} catch (SocketException e) {
e.printStackTrace();
} } else if (info.getType() == ConnectivityManager.TYPE_WIFI) {//当前使用无线网络
WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
WifiInfo wifiInfo = wifiManager.getConnectionInfo();
int ipAddress = wifiInfo.getIpAddress();//得到IPV4地址
return ((ipAddress & 0xff)+"."+(ipAddress>>8 & 0xff)+"." //将得到的int类型的IP转换为String类型
+(ipAddress>>16 & 0xff)+"."+(ipAddress>>24 & 0xff));
}
} else {
//当前无网络连接,请在设置中打开网络
}
return null;
}
}

五.Debug

六.实际运行效果

如果这篇blog对您有所帮助,请留下您的一个赞,也欢迎留言讨论,笔者将在第一时间回复!

基于TCP的安卓服务器开发的更多相关文章

  1. 基于TCP的安卓客户端开发

    一.Socket通信简介 Android与服务器的通信方式主要有两种,一是Http通信,一是Socket通信.两者的最大差异在于,http连接使用的是“请求—响应方式”,即在请求时建立连接通道,当客户 ...

  2. openfire:基于开源 Openfire 聊天服务器 - 开发Openfire聊天记录插件

    基于开源 Openfire 聊天服务器 - 开发Openfire聊天记录插件 上一篇文章介绍到怎么在自己的Java环境中搭建openfire插件开发的环境,同时介绍到怎样一步步简单的开发openfir ...

  3. 基于开源 Openfire 聊天服务器 - 开发Openfire聊天记录插件

    原文:http://www.cnblogs.com/hoojo/archive/2013/03/29/openfire_plugin_chatlogs_plugin_.html 随笔-150  评论- ...

  4. 基于Netbeans的安卓Android开发环境配置 - CSDN博客

    原文:基于Netbeans的安卓Android开发环境配置 - CSDN博客 基于Netbeans的安卓Android开发环境配置 一.准备工作 NetBeans 勾选网页中的Accept-选择对应系 ...

  5. 基于开源 Openfire 聊天服务器 - 开发Openfire聊天记录插件[转]

    上一篇文章介绍到怎么在自己的Java环境中搭建openfire插件开发的环境,同时介绍到怎样一步步简单的开发openfire插件.一步步很详细的介绍到简单插件开发,带Servlet的插件的开发.带JS ...

  6. 一个基于TCP/IP的服务器与客户端通讯的小项目(超详细版)

    1.目的:实现客户端向服务器发送数据 原理: 2.建立两个控制台应用,一个为服务器,用于接收数据.一个为客户端,用于发送数据. 关键类与对应方法: 1)类IPEndPoint: 1.是抽象类EndPo ...

  7. 基于TCP协议的服务器(多线程)

    import java.io.BufferedOutputStream; import java.io.BufferedReader; import java.io.IOException; impo ...

  8. 基于TCP协议的服务器(单线程)

    import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import  ...

  9. c++下基于windows socket的服务器客户端程序(基于UDP协议)

    前天写了一个基于tcp协议的服务器客户端程序,今天写了一个基于UDP协议的,由于在上一篇使用TCP协议的服务器中注释已经较为详细,且许多api的调用是相同的,故不再另外注释. 使用UDP协议需要注意几 ...

随机推荐

  1. Oarcle 入门之注释与关键字

    --1.--单行注释 *输入法应定要为英文 --2./*多行注释 *与java相似*/   ------------------------------------------------------ ...

  2. kubernetes1.4新特性(一):支持sysctl命令

    sysctl是一个允许改变正在运行中的Linux系统内核参数的接口.可以通过sysctl修改Linux系统内核中的TCP/IP 堆栈和虚拟内存系统的高级选项,而且不需要重新启动Linux系统,就可以实 ...

  3. undefined的几种情况

    1.变量声明了,但是没有赋值: 2.一个变量声明了,并且赋值了undefined: var a = undefined; 3.一个对象中,获取某个不存在的属性,值也是undefined

  4. MyBatis注解方式批量插入操作

    @Insert({ "<script>", "insert into table_name(column1, column2, column3) values ...

  5. MySQL5.7 多源复制监控脚本

    #!/bin/bash :<<BLOCK Version : v1.0 2018-12-21 MySQL多源复制检测脚本 监控配置放在 $CONFIG_FILE 中,内容如下 #mysql ...

  6. Python selectors实现socket并发

    selectors模块 此模块允许基于选择模块原语构建高级别和高效的I / O多路复用. 鼓励用户使用此模块,除非他们想要精确控制使用的os级别的原语. 注:selectors也是包装了select高 ...

  7. MVC输出缓存(OutputCache参数详解)

    版权声明:本文为博主原创文章,未经博主允许转载随意. https://blog.csdn.net/kebi007/article/details/59199115 1.学习之前你应该知道这些 几乎每个 ...

  8. MySql 三大知识点,索引、锁、事务,原理分析

    1.索引 索引,类似书籍的目录,可以根据目录的某个页码立即找到对应的内容. 索引的优点:1. 天生排序,2. 快速查找. 索引的缺点:1. 占用空间,2. 降低更新表的速度. 注意点:小表使用全表扫描 ...

  9. python 的运行方式和基础变量

    机器语言:直接用计算机能听的懂得二进制去编写程序,需要了解硬件细节 优点:执行效率高 缺点:开发效率低汇编语言:用英文单词取代二进制指令去编写程序 优点:开发效率高于机器语言 缺点:执行效率低于机器语 ...

  10. 尚硅谷面试第一季-18ES与Solr的区别

    背景:它们都是基于Lucene搜索服务器基础之上开发,一款优秀的,高性能的企业级搜索服务器.[是因为他们都是基于分词技术构建的倒排索引的方式进行查询] 开发语言:Java语言开发 诞生时间:Solr ...