基于TCP的安卓服务器开发

时间:2023-03-08 16:40:10

一.说明

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

六.实际运行效果

基于TCP的安卓服务器开发

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