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>
就先讲到这里啦!