基于Android的TCP服务端应用

TCP/IP是什么?

        TCP/IP(Transmission Control Protocol/Internet Protocol)是一种用于电子设备之间通过网络进行通信的标准,定义了电子设备(如计算机,路由器等)如何发送数据到另一个设备。这个协议集包括两个主要部分,传输控制协议(TCP)和网际协议(IP):

  • 启动控制协议(TCP): TCP主要负责在数据从源到目的地移动时的数据整合和错误检查。它将大块数据分解成更小的数据包,然后在接收方组装这些小的数据包成完整的消息包。

  • 网际协议(IP): IP负责数据包的发送和寻址。每一个在线的设备都至少拥有一个公共IP地址,这个地址唯一地标识了强联网上的每一个设备。IP用这些地址把数据正确送达目的

实际上就是将TCP协议与IP协议综合使用

协议分层

在应用编写上我们只需了解应用层。

套接字方法

        在应用层套接字方法(Socket methods)是网络编程中的一种用来创建并管理网络连接的工具。更具体的说,套接字提供一个编程接口(API),用于建立网络连接并进行数据发送和接收。这些方法通常来自socket这个库,它在Python,Java,C++等多种编程语言中都存在。下面是一些常见的套接字方法:

  1. socket(): 创建一个新的套接字对象。
  2. bind(): 绑定套接字到一个地址和端口。
  3. listen(): 开始监听来自客户端的连接。
  4. accept(): 接受一个客户端连接,并返回一个新的套接字和客户端的地址。
  5. connect(): 连接到远程服务器。
  6. send(): 发送数据到连接的套接字。
  7. recv(): 接收来自套接字的数据。
  8. close(): 关闭套接字连接。

使用这些方法,程序员可以创建服务器和客户端,在这两者之间建立连接,然后发送和接收数据。

代码部分 

AndroidManifest.xml 

首先我们需要对AndroidManifest.xml进行修改

<uses-permission android:name="android.permission.INTERNET"/><!--获取Internet权限-->

将上述代码插入至<manifest>首标签后。

TCPServer.java Service类

然后新建一个Service,可以命名为TCPServer

public class TCPService extends Service {
    private Intent intent;
    private ServerSocket serverSocket;
    private Socket socket;
    private BufferedReader reader;
    private PrintWriter writer;
    private boolean isRunning=false;
    private Thread tcpThread;
    private static final int port=9999;//端口定义

    @Override
    public void onCreate(){
        super.onCreate();
    }

    @Override
    public int onStartCommand(Intent intent,int flags,int startID){
        if(!isRunning&&"TCP_SERVICE_START".equals(intent.getAction())){
            isRunning=true;
            startServer();
        }//收到开启服务的意图
        else if(isRunning&&"TCP_MESSAGE_SEND".equals(intent.getAction())){
            String message=intent.getStringExtra("messageSe");
            sendMessageToClient(message);
        }//收到发送信息的意图

        return super.onStartCommand(intent, flags, startID);
    }

    @Override
    public void onDestroy(){
        super.onDestroy();
        if(isRunning){
            isRunning=false;
            try{
                serverSocket.close();
            }catch (IOException e){
                e.printStackTrace();
            }
            tcpThread.interrupt();
        }
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    private void startServer() {
        tcpThread=new Thread(() -> {
            try{
                serverSocket=new ServerSocket(port);//创建一个新的套接字对象
                while(isRunning){
                    socket=serverSocket.accept();//接受一个客户端连接,并返回一个新的套接字和客户端的地址
                    reader=new BufferedReader(new InputStreamReader(socket.getInputStream()));//读取器
                    writer=new PrintWriter(socket.getOutputStream(),true);//发送器
                    String message=reader.readLine();
                    intent=new Intent("TCP_MESSAGE_RECEIVED");
                    intent.putExtra("messageRe",message);
                    LocalBroadcastManager.getInstance(TCPService.this).sendBroadcast(intent);//通过广播可以让其它类获取收到的内容
                }
            }catch (IOException e){
                e.printStackTrace();
            }
        });
        tcpThread.start();
    }

    private void sendMessageToClient(String message){
        Thread sendThread = new Thread(() -> writer.println(message));
        sendThread.start();
        sendThread.interrupt();
    }
}

注意:在接收和发送时,应在新的线程中进行,以防进程冲突

用到的库

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;

import androidx.localbroadcastmanager.content.LocalBroadcastManager;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;

activity_main.xml和string.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <android.widget.LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <android.widget.TextView
            android:id="@+id/text_filed"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:layout_marginTop="100dp"
            android:text="@string/textview_hint"
            android:textSize="40sp" />

        <android.widget.EditText
            android:id="@+id/text_input"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:layout_marginTop="100dp"
            android:autofillHints="Hello!"
            android:inputType="text"
            android:text="@string/edittext_hint"
            android:textSize="40sp"
            tools:ignore="LabelFor" />

        <android.widget.Button
            android:id="@+id/button_send"
            android:layout_height="wrap_content"
            android:layout_width="wrap_content"
            android:layout_gravity="center_horizontal"
            android:layout_marginTop="100sp"
            android:text="@string/button_send"
            android:textSize="50sp"/>
    </android.widget.LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
<resources>
    <string name="app_name">TCPServer</string>
    <string name="textview_hint">等待接收</string>
    <string name="edittext_hint">输入要发送的内容</string>
    <string name="button_send">发送</string>
    <string name="button_status">STATUS</string>
</resources>

可以根据个人需求调整

MainActivity.java

public class MainActivity extends AppCompatActivity {
    private BroadcastReceiver receiver;
    private String messageRe,messageSe;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Intent startService = new Intent(this, TCPService.class);
        startService.setAction("TCP_SERVICE_START");
        startService(startService);//启动服务
        TextView textView=findViewById(R.id.text_filed);
        EditText editText=findViewById(R.id.text_input);
        Button button = findViewById(R.id.button_send);

        receiver=new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                messageRe="Received:"+intent.getStringExtra("messageRe");
                textView.setText(messageRe);
            }
        };
        IntentFilter filter = new IntentFilter("TCP_MESSAGE_RECEIVED");
        LocalBroadcastManager.getInstance(this).registerReceiver(receiver, filter);
        //广播接收器
        
        button.setOnClickListener(view -> {
            messageSe=editText.getText().toString();
            Intent sendMessage=new Intent(this,TCPService.class);
            sendMessage.putExtra("messageSe",messageSe);
            sendMessage.setAction("TCP_MESSAGE_SEND");
            startService(sendMessage);
        });//按钮点击监听器
    }

    @Override
    protected void onDestroy(){
        super.onDestroy();
        LocalBroadcastManager.getInstance(this).unregisterReceiver(receiver);
    }
}

用到的库 

import androidx.appcompat.app.AppCompatActivity;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

        到此完成了所有代码部分,接下来可以测试了,注意设备的IP地址、子网掩码、网关和首选DNS设置,以及IPV4和IPV6的选择,并且注意程序在端口设置中一般取8000以上。 

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论
要将Android设备作为TCP服务器,您可以使用Java的Socket类和ServerSocket类。以下是一个简单的示例: 1. 在Android Studio中创建一个新项目。 2. 在您的MainActivity类中添加以下代码: ```java public class MainActivity extends AppCompatActivity { private ServerSocket serverSocket; private Thread serverThread; private TextView serverStatus; private static final int SERVER_PORT = 8080; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); serverStatus = findViewById(R.id.server_status); serverThread = new Thread(new ServerThread()); serverThread.start(); } @Override protected void onDestroy() { super.onDestroy(); if (serverThread != null) { serverThread.interrupt(); } } private class ServerThread implements Runnable { @Override public void run() { try { serverSocket = new ServerSocket(SERVER_PORT); while (!Thread.currentThread().isInterrupted()) { Socket socket = serverSocket.accept(); // Handle client connection here // ... socket.close(); } } catch (IOException e) { e.printStackTrace(); } } } } ``` 3. 在您的布局文件中添加一个TextView,用于显示服务器状态: ```xml <TextView android:id="@+id/server_status" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Server status: running..." android:textAlignment="center" android:textSize="24sp" /> ``` 4. 运行您的应用程序,并在控制台中查看服务器状态。 请注意,在上面的示例中,我们需要在单独的线程中运行服务器。这是因为服务器在接受客户端连接时会阻塞,如果我们在主线程中运行它,将会导致应用程序挂起。另外,我们还需要在应用程序关闭时停止服务器

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

fangz688

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值