Android简单的socket网络通信例子--群聊

本文介绍了Android如何使用Socket进行简单的网络通信,特别是在群聊场景的应用。通过Java的Socket和ServerSocket类,详细阐述了连接建立的四个步骤:服务器监听、客户端请求、建立链接和通信。同时提到了在Android中需要添加Internet访问权限以避免运行时错误。

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

Android的网络通信很多都是基于socket,在这里说一下简单的Android的socket通信的例子。在这里我们模拟一下群聊。

首先我们了解一下什么是socket,socket又称“套接字”,应用程序通常通过“套接字”向网络发出请求或者应答请求。在Java中Socket和ServerSocket类库位于java.net包中。ServerSocket用于服务器端,Socket是建立网络链接使用的,连接成功后应用程序的两端都会产生一个Socket实例,操作这个实例,我们就可以完成回话了。

Socket链接建立的过程:

1.服务器监听

2.客户端发出请求

3.建立链接

4.通信

服务端的代码:

package com.example.testmysetversocket.main;

/**
 * 启动线程开始监听
 * @author Allen
 *
 */
public class MyServerSocket {

	public static void main(String[] args) {
		new ServerListener().start();
		
	}

}


package com.example.testmysetversocket.main;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

import javax.swing.JOptionPane;
/**
 * 监听客户端请求的线程类
 * @author Allen
 *
 */
public class ServerListener extends Thread {

	@Override
	public void run() {
		//1-65535
		try {
			ServerSocket serverSocket = new ServerSocket(12345);
			//循环监听来自客户端的连接
			while (true) {
				//block
				Socket socket = serverSocket.accept();
				//建立连接
				JOptionPane.showMessageDialog(null, "有客户端链接到了本机的12345端口");
				//将socket传递给新的线程
				ChatSocket cs = new ChatSocket(socket);
				cs.start();
				ChatManager.getChatManager().add(cs);
			}
			
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

package com.example.testmysetversocket.main;

import java.util.Vector;
/**
 * 管理聊天线程的类,每个客户端只有一个聊天线程
 * @author Allen
 *
 */
public class ChatManager {
	//把ChatManager单例化
	private ChatManager(){}
	private static final ChatManager cm = new ChatManager();
	public static ChatManager getChatManager() {
		return cm;
	}
	
	//ChatSocket线程管理集合
	Vector<ChatSocket> vector = new Vector<ChatSocket>();
	
	/**
	 * 添加ChatSocket
	 * @param cs
	 */
	public void add(ChatSocket cs) {
		vector.add(cs);
	}
	
	/**
	 * 向其他所有客户端发送信息
	 * @param cs
	 * @param out
	 */
	public void publish(ChatSocket cs,String out) {
		for (int i = 0; i < vector.size(); i++) {
			ChatSocket csChatSocket = vector.get(i);
			//进行判断,当前发送信息的线程就不用再接收信息了
			if (!cs.equals(csChatSocket)) {
				csChatSocket.out(out);
			}
		}
	}
}

package com.example.testmysetversocket.main;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.Socket;
/**
 * socket通信的线程类
 * @author Allen
 *
 */
public class ChatSocket extends Thread {
	
	Socket socket;
	/**
	 * 构造函数
	 * @param s
	 */
	public ChatSocket(Socket s){
		this.socket = s;
	}
	/**
	 * 输出消息到客户端
	 * @param out
	 */
	public void out(String out) {
		try {
			socket.getOutputStream().write((out+"\n").getBytes("UTF-8"));
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	/**
	 * 从客户端接收信息,并把消息发送给其他所有的客户端
	 */
	@Override
	public void run() {
		out("你已经连接到本服务器了");
		try {
			BufferedReader br = new BufferedReader(
					new InputStreamReader(
							socket.getInputStream(),"UTF-8"));
			String line = null;
			//把消息发送给其他所有客户端
			while ((line = br.readLine()) != null) {
				System.out.println(line);
				ChatManager.getChatManager().publish(this, line);
			}
			//这里注意要把当前的流关闭
			br.close();
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}
}
Android端的代码:

MainActivity布局文件

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >

        <EditText
            android:id="@+id/ip"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="0.6"
            android:hint="输入服务器的IP地址"
            android:text="10.0.2.2" >

        </EditText>

        <Button
            android:id="@+id/connect"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="0.4"
            android:text="连接" />

    </LinearLayout>

    <ScrollView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_weight="0.86" >

        <TextView
            android:id="@+id/text"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:text="Ready..." />
    </ScrollView>

    <EditText
        android:id="@+id/edit"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:hint="在这里输入内容" />

    <Button
        android:id="@+id/send"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="发送" />

</LinearLayout>

package com.example.mysocketclient;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.net.UnknownHostException;

import com.jikexueyuan.mysocketclient.R;

import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends Activity {

	EditText ip;
	EditText editText;
	TextView text;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		ip = (EditText) findViewById(R.id.ip);
		editText = (EditText) findViewById(R.id.edit);
		text = (TextView) findViewById(R.id.text);

		findViewById(R.id.connect).setOnClickListener(new View.OnClickListener() {

			@Override
			public void onClick(View arg0) {
				connect();
			}
		});

		findViewById(R.id.send).setOnClickListener(new View.OnClickListener() {

			@Override
			public void onClick(View arg0) {
				send();
			}
		});
	}

	//-------------------------------------

	Socket socket = null;
	BufferedWriter writer = null;
	BufferedReader reader = null;
	/**
	 * 建立链接
	 */
	public void connect() {

		
		AsyncTask<Void, String, Void> read = new AsyncTask<Void, String, Void>() {

			@Override
			protected Void doInBackground(Void... arg0) {
				try {
					socket = new Socket(ip.getText().toString(), 12345);
					writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
					reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
					publishProgress("@success");
				} catch (UnknownHostException e1) {
					Toast.makeText(MainActivity.this, "无法建立链接", Toast.LENGTH_SHORT).show();
				} catch (IOException e1) {
					Toast.makeText(MainActivity.this, "无法建立链接", Toast.LENGTH_SHORT).show();
				}
				try {
					String line;
					while ((line = reader.readLine())!= null) {
						publishProgress(line);
					}
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				return null;
			}

			@Override
			protected void onProgressUpdate(String... values) {
				if (values[0].equals("@success")) {
					Toast.makeText(MainActivity.this, "链接成功!", Toast.LENGTH_SHORT).show();
					
				}
				text.append("别人说:"+values[0]+"\n");
				super.onProgressUpdate(values);
			}
		};
		read.execute();

	}
	/**
	 * 发送消息
	 */
	public void send() {
		try {
			text.append("我说:"+editText.getText().toString()+"\n");
			writer.write(editText.getText().toString()+"\n");
			writer.flush();
			editText.setText("");
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

}

配置文件

注意:要加Internet访问权限,不然会报错

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.jikexueyuan.mysocketclient"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="14"
        android:targetSdkVersion="17" />
    <uses-permission android:name="android.permission.INTERNET"/>

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.example.mysocketclient.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

就先讲到这里啦!


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值