一.说明

前文介绍了基于安卓客户端的开发,在此基础上,进行少许改动即可开发出一款基于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. 移动端picker插件

    项目需要,要做移动端网页,比如选择出生日期什么的.可笑weui给的控件,竟然选择后的数据不准确. 于是自己写了一个. 链接: https://pan.baidu.com/s/1qY2SSxQ 密码: ...

  2. ESP8266使用笔记之常用固件

    开发板使用的是NodeMCU开发板: 目录 1.学习使用ESP8266官方的SDK         1.1使用SDK提供的AT固件         1.2使用SDK Build固件 2.学习使用Nod ...

  3. K8S学习笔记之ETCD启动失败注意事项

    最近搭建K8S集群遇到ETCD的报错,报错信息如下,一定要关闭防火墙.iptables和SELINUX,三个都要关闭!! Mar 26 20:39:24 k8s-m1 etcd[6437]: heal ...

  4. [c/c++] programming之路(19)、数组指针

    一.指针运算 #include<stdio.h> #include<stdlib.h> void main0(){ ; int *p=&a; printf());//变 ...

  5. A4988和CNC SHIELD使用方法 步进电机

    接线视频 点这看视频 来源 https://www.basemu.com/a4988_pinout_and_how_to_use.html 注意要点 A4988既要12V外部供电,也要5V逻辑供电 我 ...

  6. zabbix-3.4.14源码安装

    此次介绍一下,zabbix的源码安装,因为zabbix的依赖很多,所以源码安装有很多依赖需要安装 首先,下载zabbix源码包 wget https://nchc.dl.sourceforge.net ...

  7. _pvp

    comment 备注 zone 区域ID,.gps第二个参数 area 地域ID,.gps第三个参数 type 区域类型(保持原状.安全区.自由PVP.自由PVP - 禁止组队.自定义阵营(_fact ...

  8. HDU 2612 (2次BFS,有点小细节)

    Problem Description Pass a year learning in Hangzhou, yifenfei arrival hometown Ningbo at finally. L ...

  9. Redis入门指南之三(入门)

    本节主要介绍Redis的5种数据类型,同时使用Python API来操作Redis,其中python版本为3.5, redis版本为4.0.2. redis-py 的API的使用可以分类为: (1)连 ...

  10. 【Mybatis】【1】generate批量生成实体类,数据库接口类和mapper

    前言: 1,实体类之类如果自己写的话,比较繁琐,还容易出错,所以用generate自动生成 2,int类型可能会生成为short类型,建议不要手动改回int类.因为下次生成又是short类型了,可能会 ...