一.说明

前文介绍了基于安卓客户端的开发,在此基础上,进行少许改动即可开发出一款基于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. java实现zip压缩和解压工具

    引入ant.jar package com.develop.web.util; import java.io.BufferedInputStream; import java.io.File; imp ...

  2. 1.1:Get Started with Unity Shaders

    文章著作权归作者所有.转载请联系作者,并在文中注明出处,给出原文链接. 本系列原更新于作者的github博客,这里给出链接. 第1章开始正式进入Unity Shader的学习. 什么是Shader 本 ...

  3. jquery简易tab切换

    切换tab 使用eq()函数 eq() 方法将匹配元素集缩减值指定 index 上的一个. //为项目 3 设置红色背景 <ul> <li>list item 1</li ...

  4. Python Mysql 交互

    Mysql 安装Python模块   Linux: yum install MySQL-python Windos: http://files.cnblogs.com/files/wupeiqi/py ...

  5. ts文件编译后变量在vscode里报错

    需要将编译过的同名js文件删除才可以

  6. this指向问题,只提供案例,不做任何分析

    希望大家在测试的道路上找到答案,阔步前行 <script type="text/javascript"> /*this指向 console.log(this); fun ...

  7. scala 入门Eclipse环境搭建

    scala 入门Eclipse环境搭建及第一个入门经典程序HelloWorld IDE选择并下载: scala for eclipse 下载: http://scala-ide.org/downloa ...

  8. 使用Flask部署机器学习模型

    Introduction A lot of Machine Learning (ML) projects, amateur and professional, start with an aplomb ...

  9. jQuery validator plugin之Plugin Method

    原文 .validate() validate( [options ] ) options Type: Object debug (default: false) Type: Boolean Enab ...

  10. JDK下载-安装-配置

    1.JDK的下载 jdk1.8版本   下载地址: http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-213 ...