愿君学长松,慎勿作桃李。这篇文章主要讲述基于TCP的安卓服务器开发相关的知识,希望能为你提供帮助。
一.说明前文介绍了基于安卓客户端的开发,在此基础上,进行少许改动即可开发出一款基于TCP的安卓服务器,理论知识请参见笔者上一篇博文,下面直接实践操作。
二.权限申明
1< !--允许应用程序改变网络状态--> 2< uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/> 3 4< !--允许应用程序改变WIFI连接状态--> 5< uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/> 6 7 8< !--允许应用程序访问有关的网络信息--> 9< uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> 10 11< !--允许应用程序访问WIFI网卡的网络信息--> 12< uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/> 13 14< !--允许应用程序完全使用网络--> 15< uses-permission android:name="android.permission.INTERNET"/>
三.布局文件
1 < ?xml version="1.0" encoding="utf-8"?> 2 < LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 3android:orientation="vertical" android:layout_width="match_parent" 4android:layout_height="match_parent"> 5< LinearLayout 6android:layout_width="match_parent" 7android:layout_height="wrap_content" 8android:layout_marginLeft="10dp" 9android:layout_marginRight="10dp" 10android:layout_marginTop="10dp" 11android:layout_marginBottom="10dp"> 12< TextView 13android:id="@+id/LocalIPTextView" 14android:layout_width="match_parent" 15android:layout_height="wrap_content" 16android:hint="本机IP:" 17android:textSize="25dp"/> 18< /LinearLayout> 19< LinearLayout 20android:layout_width="match_parent" 21android:layout_height="wrap_content" 22android:layout_marginLeft="10dp" 23android:layout_marginRight="10dp" 24android:layout_marginBottom="10dp"> 25> 26< EditText 27android:id="@+id/MessagetoSendEditText" 28android:layout_width="0dp" 29android:layout_height="match_parent" 30android:layout_weight="3" 31android:text="Data from Server"/> 32< Button 33android:id="@+id/SendButton" 34android:layout_width="0dp" 35android:layout_height="wrap_content" 36android:layout_weight="1" 37android:text="发送"/> 38< /LinearLayout> 39 40< LinearLayout 41android:layout_width="match_parent" 42android:layout_height="wrap_content" 43android:layout_marginLeft="10dp" 44android:layout_marginRight="10dp" 45 46android:layout_marginBottom="10dp"> 47< TextView 48android:id="@+id/DisplayTextView" 49android:layout_width="match_parent" 50android:layout_height="wrap_content" 51android:textSize="25dp"/> 52< /LinearLayout> 53 54 55 < /LinearLayout>
【基于TCP的安卓服务器开发】
四.具体实现代码
1 package com.example.john.androidsockettest; 2 3 import android.content.Context; 4 import android.net.ConnectivityManager; 5 import android.net.NetworkInfo; 6 import android.net.wifi.WifiInfo; 7 import android.net.wifi.WifiManager; 8 import android.os.Handler; 9 import android.os.Message; 10 import android.support.v7.app.AppCompatActivity; 11 import android.os.Bundle; 12 import android.view.View; 13 import android.widget.Button; 14 import android.widget.EditText; 15 import android.widget.TextView; 16 17 import java.io.BufferedReader; 18 import java.io.IOException; 19 import java.io.InputStreamReader; 20 import java.io.OutputStream; 21 import java.net.Inet4Address; 22 import java.net.InetAddress; 23 import java.net.NetworkInterface; 24 import java.net.ServerSocket; 25 import java.net.Socket; 26 import java.net.SocketException; 27 import java.util.Enumeration; 28 29 public class MainActivity extends AppCompatActivity { 30 31//线程及套接字定义 32public Socket socket = null; 33public ServerSocket serverSocket = null; 34private AcceptThread acceptThread = null; 35private ReceiveThread receiveThread = null; 36private SendThread sendThread = null; 37//Handler中的消息类型 38public static final int DEBUG = 0x00; 39public static final int RECEIVEDATAFROMCLIENT = 0x01; 40public static final int SENDDATATOCLIENT = 0x02; 41//控件 42private TextView localIPTextView; 43private EditText messagetoSendEditText; 44private Button sendButton; 45private TextView displayTextView; 46//变量定义 47String messagetoSend=""; 48 49public Handler myHandler = new Handler() { 50@Override 51public void handleMessage(Message msg) { 52if (msg.what == RECEIVEDATAFROMCLIENT) { 53Bundle bundle = msg.getData(); 54displayTextView.append("Client:"+bundle.getString("string1")+"\\n"); 55} 56else if (msg.what == DEBUG) { 57Bundle bundle = msg.getData(); 58displayTextView.append("Debug:"+bundle.getString("string1")+"\\n"); 59} 60else if (msg.what == SENDDATATOCLIENT) { 61Bundle bundle = msg.getData(); 62displayTextView.append("Server:"+bundle.getString("string1")+"\\n"); 63} 64} 65 66}; 67//子线程更新UI 68public void SendMessagetoHandler(final int messageType , String string1toHandler){ 69Message msg = new Message(); 70msg.what = messageType; //消息类型 71Bundle bundle = new Bundle(); 72bundle.clear(); 73bundle.putString("string1", string1toHandler); //向bundle中添加字符串 74msg.setData(bundle); 75myHandler.sendMessage(msg); 76} 77@Override 78protected void onCreate(Bundle savedInstanceState) { 79super.onCreate(savedInstanceState); 80setContentView(R.layout.activity_main); 81//控件对象获取 82localIPTextView = (TextView)findViewById(R.id.LocalIPTextView); 83messagetoSendEditText = (EditText)findViewById(R.id.MessagetoSendEditText); 84sendButton = (Button)findViewById(R.id.SendButton); 85displayTextView = (TextView)findViewById(R.id.DisplayTextView); 86//服务器IP获取显示 87localIPTextView.setText("本机IP:"+getIPAddress(this)); 88//开启接受线程 89acceptThread = new AcceptThread(); 90acceptThread.start(); 91sendButton.setOnClickListener(new View.OnClickListener() { 92 93@Override 94public void onClick(View v) { 95messagetoSend = messagetoSendEditText.getText().toString(); 96//使用连接成功后得到的socket构造发送线程,每点击一次send按钮触发一次发送线程 97sendThread = new SendThread(socket); 98sendThread.start(); 99} 100}); 101 102} 103//*****接受线程***** 104class AcceptThread extends Thread{ 105@Override 106public void run() { 107try{ 108serverSocket = new ServerSocket(8086); 109socket = serverSocket.accept(); 110}catch (IOException e){ 111e.printStackTrace(); 112} 113SendMessagetoHandler(DEBUG,"客户端连接成功!"); 114//构造并开启接收线程 115receiveThread = new ReceiveThread(socket); 116receiveThread.start(); 117} 118} 119//********接收线程********** 120class ReceiveThread extends Thread{ 121 122private Socket mSocket; 123//接收线程的构造函数,由接受线程传入套接字 124public ReceiveThread(Socket socket){mSocket = socket; } 125@Override 126public void run() { 127while(true){//连接成功后将一直运行 128try { 129BufferedReader bufferedReader; 130String line = null; 131String readBuffer=""; 132bufferedReader = new BufferedReader(new InputStreamReader(mSocket.getInputStream())); 133 134while ((line = bufferedReader.readLine()) != null) { 135readBuffer = line + readBuffer; 136SendMessagetoHandler(RECEIVEDATAFROMCLIENT,readBuffer); 137readBuffer = ""; 138} 139 140}catch (IOException e) { 141e.printStackTrace(); 142//更新UI:显示发送错误信息 143SendMessagetoHandler(DEBUG,"接收失败!"); 144return; 145} 146} 147} 148} 149//********发送线程********** 150class SendThread extends Thread{ 151private Socket mSocket; 152//发送线程的构造函数,由接受线程传入套接字 153public SendThread(Socket socket) {mSocket = socket; } 154 155@Override 156public void run() { 157try{ 158OutputStream outputStream = mSocket.getOutputStream(); 159//向服务器发送信息 160outputStream.write(messagetoSend.getBytes("gbk")); 161outputStream.flush(); 162//更新UI:显示发送出的数据 163SendMessagetoHandler(SENDDATATOCLIENT,messagetoSend); 164}catch (IOException e) { 165e.printStackTrace(); 166//更新UI:显示发送错误信息 167SendMessagetoHandler(DEBUG,"发送失败!"); 168return; 169} 170} 171} 172//*****获取本机的ip地址 173private String getlocalip(){ 174WifiManager wifiManager = (WifiManager)this.getApplicationContext().getSystemService(Context.WIFI_SERVICE); 175WifiInfo wifiInfo = wifiManager.getConnectionInfo(); 176int ipAddress = wifiInfo.getIpAddress(); 177//Log.d(Tag, "int ip "+ipAddress); 178if(ipAddress==0)return null; 179return ((ipAddress & 0xff)+"."+(ipAddress> > 8 & 0xff)+"." 180+(ipAddress> > 16 & 0xff)+"."+(ipAddress> > 24 & 0xff)); 181} 182 183public static String getIPAddress(Context context) { 184NetworkInfo info = ((ConnectivityManager) context 185.getSystemService(Context.CONNECTIVITY_SERVICE)).getActiveNetworkInfo(); 186if (info != null & & info.isConnected()) { 187if (info.getType() == ConnectivityManager.TYPE_MOBILE) {//当前使用2G/3G/4G网络 188try { 189//Enumeration< NetworkInterface> en=NetworkInterface.getNetworkInterfaces(); 190for (Enumeration< NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements(); ) { 191NetworkInterface intf = en.nextElement(); 192for (Enumeration< InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements(); ) { 193InetAddress inetAddress = enumIpAddr.nextElement(); 194if (!inetAddress.isLoopbackAddress() & & inetAddress instanceof Inet4Address) { 195return inetAddress.getHostAddress(); 196} 197} 198} 199} catch (SocketException e) { 200e.printStackTrace(); 201} 202 203} else if (info.getType() == ConnectivityManager.TYPE_WIFI) {//当前使用无线网络 204WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); 205WifiInfo wifiInfo = wifiManager.getConnectionInfo(); 206int ipAddress = wifiInfo.getIpAddress(); //得到IPV4地址 207return ((ipAddress & 0xff)+"."+(ipAddress> > 8 & 0xff)+"."//将得到的int类型的IP转换为String类型 208+(ipAddress> > 16 & 0xff)+"."+(ipAddress> > 24 & 0xff)); 209} 210} else { 211//当前无网络连接,请在设置中打开网络 212} 213return null; 214} 215 }
五.Debug
六.实际运行效果
文章图片
如果这篇blog对您有所帮助,请留下您的一个赞,也欢迎留言讨论,笔者将在第一时间回复!
推荐阅读
- redis persistence 之 append only file
- Software Engineering——A PRACTITIONER'S APPROACH (english edition · eighth edition)
- 外部浏览器打开app置顶页面
- shiro实现app和web统一登录
- andorid HTTPS不需要证书VolleyEror: com.android.volley.NoConnectionError: javax.net.ssl.SSLHandshakeE
- Android NDK 环境搭建
- Android Studio之Activity切换动画
- android控件
- 如何编写和精灵宝可梦一样的 app()