最近,做项目需要使用Android(客户端)与Linux(服务器端)进行数据通信,这学期也刚好学习了Linux网络编程的一些知识。所以,实现了一个小Demo,供有需要的朋友参考一下。

效果如下:

客户端向服务器端发送字符串数据,服务器收到客户端的数据显示在Linux终端上,并往客户端回发接收到的数据。客户端把发往服务器端的数据与接收到的数据都显示在一个TextView上面。

Linux服务器端:

Android客户端:

首先,有几个小问题要注意一下:

1. 在Android应用程序需要使用Tcp协议进行通信时,需要在AndroidManifest.xml中添加以下权限:
uses-permission android:name=”android.permission.INTERNET”

2. 在真机上面运行调试程序时,要保证手机能Ping通Linux服务器端的IP地址。

3. Android客户端接收数据,最好开一个线程来接收数据,因为是接收数据的read()方法是阻塞式的方法。

代码如下

Linux服务器端:(Server.c)

#include #include #include #include #include #include #include #include #define PORT 8888               //服务器端监听端口号#define MAX_BUFFER 1024         //数据缓冲区最大值int main(){    struct sockaddr_in server_addr, client_addr;    int server_sockfd, client_sockfd;    int size, write_size;    char buffer[MAX_BUFFER];    if ((server_sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)    //创建Socket    {        perror("Socket Created Failed!\n");        exit(1);    }    printf("Socket Create Success!\n");    server_addr.sin_family = AF_INET;    server_addr.sin_addr.s_addr = htonl(INADDR_ANY);    server_addr.sin_port = htons(PORT);    bzero(&(server_addr.sin_zero), 8);    int opt = 1;    int res = setsockopt(server_sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));    //设置地址复用    if (res < 0)    {        perror("Server reuse address failed!\n");        exit(1);    }    if (bind(server_sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1)  //绑定本地地址    {        perror("Socket Bind Failed!\n");        exit(1);    }    printf("Socket Bind Success!\n");    if (listen(server_sockfd, 5) == -1)                 //监听    {        perror("Listened Failed!\n");        exit(1);    }    printf("Listening ....\n");    socklen_t len = sizeof(client_addr);    printf("waiting connection...\n");    if ((client_sockfd = accept(server_sockfd, (struct sockaddr *)&client_addr, &len)) == -1)  //等待客户端连接    {        perror("Accepted Failed!\n");        exit(1);    }    printf("connection established!\n");    printf("waiting message...\n");    while (1)    {        memset(buffer, 0, sizeof(buffer));                             //清空数据缓冲区        if ((size = read(client_sockfd, buffer, MAX_BUFFER)) == -1)    //读取客户端的数据        {            perror("Recv Failed!\n");            exit(1);        }        if (size != 0)                                                       {            buffer[size] = '\0';            printf("Recv msg from client: %s\n", buffer);            if ((write_size = write(client_sockfd, buffer, MAX_BUFFER)) > 0)   //把收到的数据回发给客户端            {                printf("Sent msg to client successfully!\n");            }        }    }    close(client_sockfd);   //关闭Socket    close(server_sockfd);    return 0;}

Android客户端:

activity_main.xml:

<?xml version="1.0" encoding="utf-8"?><LinearLayout 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"    android:paddingBottom="@dimen/activity_vertical_margin"    android:paddingLeft="@dimen/activity_horizontal_margin"    android:paddingRight="@dimen/activity_horizontal_margin"    android:paddingTop="@dimen/activity_vertical_margin"    android:orientation="vertical"    tools:context="com.example.blog_tcp_demo.MainActivity">    <LinearLayout        android:orientation="vertical"        android:layout_width="match_parent"        android:layout_height="wrap_content">        <LinearLayout            android:layout_width="match_parent"            android:layout_height="wrap_content">            <TextView                android:text="地址:"                android:textSize="20dp"                android:layout_width="60dp"                android:layout_height="40dp" />            <EditText                android:id="@+id/edtTxt_Addr"                android:layout_weight="1"                android:layout_width="wrap_content"                android:layout_height="wrap_content" />        LinearLayout>                  //地址        <LinearLayout            android:layout_width="match_parent"            android:layout_height="wrap_content">            <TextView                android:text="端口:"                android:textSize="20dp"                android:layout_width="60dp"                android:layout_height="40dp" />            <EditText                android:id="@+id/edtTxt_Port"                android:layout_weight="1"                android:layout_width="wrap_content"                android:layout_height="wrap_content" />        LinearLayout>                  //端口        <ToggleButton            android:id="@+id/tglBtn"            android:textOn="断开"            android:textOff="连接"            android:layout_weight="1"            android:layout_width="match_parent"            android:layout_height="wrap_content" />                  //连接-断开按钮        <ScrollView            android:layout_width="fill_parent"            android:layout_height="300dp"            android:layout_weight="0.86" >            <TextView                android:id="@+id/tv_Msg"                android:layout_width="fill_parent"                android:layout_height="fill_parent"                android:text="Ready...\n" />        ScrollView>                    //消息显示        <LinearLayout            android:orientation="vertical"            android:layout_width="match_parent"            android:layout_height="wrap_content">            <EditText                android:id="@+id/edtTxt_Data"                android:hint="请输入要发送的数据"                android:layout_weight="1"                android:layout_width="match_parent"                android:layout_height="wrap_content" />            <Button                android:id="@+id/btn_Send"                android:text="发送"                android:textSize="20dp"                android:layout_width="match_parent"                android:layout_height="wrap_content" />        LinearLayout>                  //数据发送    LinearLayout>LinearLayout>

MainActivity.java:

package com.example.blog_tcp_demo;import android.content.Intent;import android.graphics.Bitmap;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.view.View;import android.widget.Button;import android.widget.CompoundButton;import android.widget.EditText;import android.widget.TextView;import android.widget.Toast;import android.widget.ToggleButton;import java.io.IOException;public class MainActivity extends AppCompatActivity {    private EditText edtTxt_Addr;    private EditText edtTxt_Port;    private ToggleButton tglBtn;    private TextView tv_Msg;    private EditText edtTxt_Data;    private Button btn_Send;    private TcpClientConnector connector;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        InitWidgets();        connector = TcpClientConnector.getInstance();   //获取connector实例        tglBtn.setOnCheckedChangeListener(new TglBtnCheckedChangeEvents());        btn_Send.setOnClickListener(new ButtonClickEvent());    }    /***     * 控件初始化     */    private void InitWidgets(){        edtTxt_Addr = (EditText) findViewById(R.id.edtTxt_Addr);        edtTxt_Port = (EditText) findViewById(R.id.edtTxt_Port);        tglBtn = (ToggleButton) findViewById(R.id.tglBtn);        tv_Msg = (TextView) findViewById(R.id.tv_Msg);        edtTxt_Data = (EditText) findViewById(R.id.edtTxt_Data);        btn_Send = (Button) findViewById(R.id.btn_Send);    }    class TglBtnCheckedChangeEvents implements ToggleButton.OnCheckedChangeListener{        @Override        public void onCheckedChanged(CompoundButton btnView, boolean isChecked){            if(btnView == tglBtn){                if(isChecked == true){                    //连接Tcp服务器端                    //connector.createConnect("172.16.46.41",8888);   //调试使用                    connector.createConnect(edtTxt_Addr.getText().toString(),Integer.parseInt(edtTxt_Port.getText().toString()));                    connector.setOnConnectListener(new TcpClientConnector.ConnectListener() {                        @Override                        public void onReceiveData(String data) {                            //Received Data,do somethings.                            tv_Msg.append("Server:"+ data + "\n");                        }                    });                }else{                    try{   //断开与服务器的连接                        connector.disconnect();                    }catch(IOException e){                        e.printStackTrace();                    }                }            }        }    }    class ButtonClickEvent implements View.OnClickListener{        public void onClick(View v){            if (v == btn_Send){                //发送数据                try{                    connector.send(edtTxt_Data.getText().toString());                    tv_Msg.append("Client:"+ edtTxt_Data.getText().toString() + "\n");                }catch (IOException e){                    e.printStackTrace();                }            }        }    }}

TcpClientConnector.java:

package com.example.blog_tcp_demo;import android.os.Bundle;import android.os.Handler;import android.os.Message;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.net.Socket;public class TcpClientConnector {    private static TcpClientConnector mTcpClientConnector;    private Socket mClient;    private ConnectListener mListener;    private Thread mConnectThread;    public interface ConnectListener {        void onReceiveData(String data);    }    public void setOnConnectListener(ConnectListener listener) {        this.mListener = listener;    }    public static TcpClientConnector getInstance() {        if (mTcpClientConnector == null)            mTcpClientConnector = new TcpClientConnector();        return mTcpClientConnector;    }    Handler mHandler = new Handler() {        @Override        public void handleMessage(Message msg) {            super.handleMessage(msg);            switch (msg.what) {                case 100:                    if (mListener != null) {                        mListener.onReceiveData(msg.getData().getString("data"));                    }                    break;            }        }    };    public void createConnect(final String mSerIP, final int mSerPort) {        if (mConnectThread == null) {            mConnectThread = new Thread(new Runnable() {                @Override                public void run() {                    try {                        connect(mSerIP, mSerPort);                    } catch (IOException e) {                        e.printStackTrace();                    }                }            });            mConnectThread.start();        }    }    /**     * 与服务端进行连接     *     * @throws IOException     */    private void connect(String mSerIP, int mSerPort) throws IOException {        if (mClient == null) {            mClient = new Socket(mSerIP, mSerPort);        }        InputStream inputStream = mClient.getInputStream();        byte[] buffer = new byte[1024];        int len = -1;        while ((len = inputStream.read(buffer)) != -1) {            String data = new String(buffer, 0, len);            Message message = new Message();            message.what = 100;            Bundle bundle = new Bundle();            bundle.putString("data", data);            message.setData(bundle);            mHandler.sendMessage(message);        }    }    /**     * 发送数据     *     * @param data 需要发送的内容     */    public void send(String data) throws IOException {        OutputStream outputStream = mClient.getOutputStream();        outputStream.write(data.getBytes());    }    /**     * 断开连接     *     * @throws IOException     */    public void disconnect() throws IOException {        if (mClient != null) {            mClient.close();            mClient = null;        }    }}

其中,Android客户端的代码参考了这位朋友的博客(^__^) ,写得的确很好,给个大写的赞!:Android Socket 通信

更多相关文章

  1. Android基于TCP和URL协议的网络编程示例【附demo源码下载】
  2. 2012年移动互联网数据报告探讨
  3. 【Android】SQLiteOpenHelper类(sql语句实现增删改查),封装SQLite
  4. Android使用SQLITE3 WAL模式
  5. 每天学习一个Android中的常用框架——2.greenDao
  6. Android进阶高手(五)之Android聊天室(4)---完结篇
  7. 常见ACTION的用法
  8. 对新浪微博android客户端中ListView的实现
  9. Android智能手机中各种音频场景下的audio data path

随机推荐

  1. 获得android手机的联网状态
  2. [android] Activity 的生命周期 以及横屏
  3. Android(安卓)demo倒计时原理(CountDownT
  4. Android下图像文件获取方式小结
  5. Android切换前后置摄像头并录制视频
  6. Android(安卓)build.prop修改详细说明
  7. arcgis for android 学习 - (8) 空间查询
  8. android小游戏 飞机躲子弹
  9. cocos2dx出现 Fatal signal 11 (SIGSEGV)
  10. android client随机验证码生成函数