Android使用Socket通信

博客围绕网络通信展开,涉及Java多线程、C# Socket通信和Android Handler消息处理。介绍了相关技术知识,展示了Android登录、客户端和服务端界面截图,给出核心代码。还总结了通信中的问题及解决方法,实现了Android与C#、Android与Android的通信功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在学习Socket之前,我们需要掌握一些知识,如java多线程,Handler等.

Java多线程

https://blog.youkuaiyun.com/qq_40318498/article/details/84726026

C#Socket通信

https://blog.youkuaiyun.com/qq_40318498/article/details/90384688

Android Handler消息处理

https://blog.youkuaiyun.com/qq_40318498/article/details/89897690




源码已上传到github上

https://github.com/Githubforusc2018/AndroidSocket




使用技术

1.Handler
2.多线程
3.网络编程

Android登录界面截图

在这里插入图片描述

Android客户端界面截图

在这里插入图片描述

Android服务端界面截图

在这里插入图片描述




Client客户端核心代码

	//连接服务器,返回的是一个Socket对象的连接来保持与服务器的通信.
	int port = Integer.parseInt(clientPort.getText().toString());
    mysocket = new Socket(clientIp.getText().toString(),port); //连成功了,服务器一直显示数据.
    //一个子线程,循环读取消息.
    while(true){
	    InputStream is = mysocket.getInputStream(); //192.168.43.224手机的wifi ip 地址.
	    byte[] buffer = new byte[1024*1024];
	    int len = is.read(buffer);	//获取输入流,读取从服务端发送过来的消息.
	    String result = new String(buffer, 0, len);
	    /*  第一次读到的是Ip地址,必须保存.*/
	    if (mycount++==1){
	        myIp = result;	//这里是与C#服务端通信的需求,我是检测是否正常连接用的.
	    }
	    Message message = new Message();	
	    message.what = 1;   //标识符为1,表明显示在自己的消息框
	    Bundle bundle = new Bundle();
	    bundle.putString("msg", result);	//将读取到的信息传入handler中处理.
	    message.setData(bundle);
	    handler.sendMessage(message);
	}
	//发送消息,这里直接使用mysocket.getOutputStream()也可以.
	DataOutputStream writer = new DataOutputStream(mysocket.getOutputStream());
    writer.write(clientMessage.getText().toString().getBytes());	//发送消息
    //发送,我也要写入handler中.
    Message message = new Message();
    message.what = 1;   //标识符为1,表明显示在自己的消息框
    Bundle bundle = new Bundle();
    bundle.putString("msg", myIp+" : "+clientMessage.getText().toString());  //ip + 说明
    message.setData(bundle);
    handler.sendMessage(message);
    //Handler
    public Handler handler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            if (msg.what==1){
                Bundle data = msg.getData();
                sb.append(data.getString("msg"));	//StringBuffer sb = new StringBuffer();这里直接不用这个也可以.
                sb.append("\n");
                serverMessageText.setText(sb.toString());
            }
        }
    };

Server服务端端核心代码

	//设置一个端口,监听客户端的连接,监听手机服务端50000端口.
	serverSocket = new ServerSocket(50000); //绑定sport
    clientSocket = serverSocket.accept();   //serverSocket是该服务器的,clientSocket返回客户端的ip和端口.
    //clientSocket.toString返回的是socket(192.168.1.107 + port)
    //userText.setText(clientSocket.toString());  报错???,使用handler处理成功.
    //读取消息,开启一个子线程,反复监听消息.
    while(true){
        //一开始客户端能给服务端发消息,服务端不能给客户端发消息,幸好解决了           
	    InputStream is = clientSocket.getInputStream();
	    byte[] buffer = new byte[1024*1024];
	    int len = is.read(buffer);
	    String result = new String(buffer, 0, len);	//读消息跟发送消息与客户端几乎一致.
	    Message message = new Message();
	    Bundle bundle = new Bundle();
	    bundle.putString("msg",result);
	    message.setData(bundle);
	    message.what = 1;   //标识符为1
	    handler.sendMessage(message);
	}
	//发送消息,也是需要开启一个线程.
	OutputStream writer = clientSocket.getOutputStream();
    writer.write(normalMessage.getText().toString().getBytes());   //发给1看看.
    String result = "发送成功";
    Message message = new Message();
    Bundle bundle = new Bundle();
    bundle.putString("msg",result);
    message.setData(bundle);
    //发送handler,更新ui
    message.what=1;
    handler.sendMessage(message);
    
    @SuppressLint("HandlerLeak")
    public Handler handler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            if (msg.what==1){
                Bundle data = msg.getData();
                sb.append(data.getString("msg"));
                sb.append("\n");
                normalText.setText(sb.toString());
            }
        }
    };

主界面中的图片切换动作使用handler处理和动画处理.
ListView客户端和ListView服务端在以上基础上,使用listview组件来显示消息,这里我对格式弄了一个处理,因此可能无法使用ListView客户端来与c#客户端进行数据交换,而只能使用Android与Android进行通信,可以解决该问题,如下.

	//Server服务端发送消息
	String result = userText.getText().toString() + "-" + classText.getText().toString() + "-" + ageText.getText().toString();
	//发送的是userText 内容 classText 内容 ageText内容 中间使用 - 来分割,这样容易把一串字节流按指定格式分割成我们想要的部分.
    writer.write(result.getBytes());
    //Client客户端
    Text = result.split("-");   //按分开.
    HashMap<String,Object> map = new HashMap<String, Object>();
    map.put("User",Text[0]);
    map.put("Class",Text[1]);
    map.put("Age",Text[2]);
    mylist.add(map);
    //我们发现,若C#服务端发送过来的消息不包含-因此Text[0] = result,Text[1],Text[2]抛出下标越界异常.
    //修改.
    int i=0;
    for(i=0;i<result.length();i++){
        if (result.charAt(i)=='-'){
            break;
        }
    }
    if (i==result.length()){
        //说明是C#发送过来的,对Text进行处理.
        Text[0] = result;
        Text[1] = "null";
        Text[2] = "null";
    }else{
        Text = result.split("-");   //按分开.
    }



Java split测试

在这里插入图片描述




一些总结:

1.服务端(假设是模拟机)可以向手机(服务端)发送请求连接,因此知道手机的ip地址能够正常连接,而手机客户端无法通过电脑的ip地址访问到模拟机(服务端),若要连接,需要知道模拟机的ip地址.

2.一个Message只能传给一个handler,若要使用handler处理多个任务,需要初始化多个Message.

3.可以使用bundle向handler中(可以是同一个活动)传递数据,在handler中使用Bundle bundle = msg.getData()来获取数据。

4.在退出活动的时候,需要关闭I/O流和socket连接.

5.使用5个write,怎么第一个输出有换行,明明程序中没有换行,最后写成一行可以解决该问题.
(若不写成一个write,可以通过trim()方法去掉多余的空格和换行)

6.Handler是Android提供的一个用来更新UI的机制(Android不允许在子线程更新UI),也是一个消息处理的机制

7.一些超时的任务处理,如网络下载等需要使用子线程来完成,因此默认情况下,主线程等待5s以上就会关闭该活动。




功能:

1.在C#Socket通信的基础上,增加Android Socket通信
2.能够让Android跟C#通信
3.能够让Android与Android进行通信.

Android使用Socket进行通信可以通过以下步骤实现。下面是一个简单的示例代码,展示了如何在Android应用中使用Socket进行客户端和服务器之间的通信。 ### 服务器端代码(Java) 首先,我们需要一个简单的服务器端代码来接收客户端的连接请求并发送数据。 ```java import java.io.*; import java.net.ServerSocket; import java.net.Socket; public class Server { public static void main(String[] args) { try { ServerSocket serverSocket = new ServerSocket(8888); System.out.println("Server started. Waiting for client..."); Socket clientSocket = serverSocket.accept(); System.out.println("Client connected."); BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true); String message; while ((message = in.readLine()) != null) { System.out.println("Received message: " + message); out.println("Server response: " + message); } in.close(); out.close(); clientSocket.close(); serverSocket.close(); } catch (IOException e) { e.printStackTrace(); } } } ``` ### 客户端代码(Android) 接下来,我们编写Android客户端代码来连接服务器并发送和接收数据。 ```java import android.os.Bundle; import android.os.StrictMode; import android.widget.TextView; import androidx.appcompat.app.AppCompatActivity; import java.io.*; import java.net.Socket; public class MainActivity extends AppCompatActivity { private TextView textView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); textView = findViewById(R.id.textView); // 允许在主线程中进行网络操作(不推荐,仅用于示例) StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build(); StrictMode.setThreadPolicy(policy); connectToServer(); } private void connectToServer() { new Thread(new Runnable() { @Override public void run() { try { Socket socket = new Socket("localhost", 8888); BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream())); PrintWriter out = new PrintWriter(socket.getOutputStream(), true); out.println("Hello, Server!"); String response = in.readLine(); runOnUiThread(new Runnable() { @Override public void run() { textView.setText(response); } }); in.close(); out.close(); socket.close(); } catch (IOException e) { e.printStackTrace(); } } }).start(); } } ``` ### 说明 1. **服务器端**:服务器端代码使用Java编写,监听8888端口,等待客户端连接。接收到客户端发送的消息后,服务器会回传一条消息。 2. **客户端**:Android客户端代码通过Socket连接到服务器,发送一条消息接收服务器响应,然后将响应显示在TextView中。 ### 注意事项 - **网络权限**:在AndroidManifest.xml中添加网络权限。 ```xml <uses-permission android:name="android.permission.INTERNET" /> ``` - **主线程网络操作**:示例代码中在主线程中进行网络操作,这是不推荐的。实际开发中应使用异步任务或其他线程处理网络操作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值