大家好:
这是我第一次写微博,写的不好之处请留言告知,谢谢。下面就来谈谈我对Socket的理解。
Socket通信的原理还是比较简单的,它大致分为以下几个步骤。
服务器端的步骤如下:
(1)建立服务器端的Socket,开始侦听整个网络中的连接请求。
(2)当检测到来自客户端的连接请求时,向客户端发送收到连接请求的信息,并建立与客户端之间的连接。
(3)当完成通信后,服务器关闭与客户端的Socket连接。
客户端的步骤如下:
(1)建立客户端的Socket,确定要连接的服务器的主机名和端口。
(2)发送连接请求到服务器,并等待服务器的回馈信息。
(3)连接成功后,与服务器进行数据的交互。
(4)数据处理完毕后,关闭自身的Socket连接。
下面我们就仿照微信来做个简单的Scoket聊天:
首先是写个服务器 SocketServer.java
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
public class SocketServer{
//所有在线的用户
public static List<WeixinServerThread> sockets = new ArrayList<WeixinServerThread>();
public static void main(String[] args) {
new SocketServer().start();
}
public void start(){
System.out.println("服务启动...");
try {
//建立一个服务等待客户端的连接
final ServerSocket server = new ServerSocket(9090);
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
try {
//与客户端建立上了连接
Socket socket = server.accept();
WeixinServerThread newSocket = new WeixinServerThread(socket);
System.out.println("上线:"+newSocket);
//1.新用户要知道所有在线的用户
for (WeixinServerThread oldSocket : sockets) {
//自定义协议
newSocket.sendMsg("refresh@"+oldSocket.ip+"@"+oldSocket.port);
}
//2.告诉所有在线的用户,俺们上来了
for (WeixinServerThread oldSocket : sockets) {
oldSocket.sendMsg("refresh@"+newSocket.ip+"@"+newSocket.port);
}
sockets.add(newSocket);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}).start();
} catch (Exception e) {
e.printStackTrace();
}
}
}
//WeixinServerThread.java是将服务器里面Socket封装成一个线程
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.StringTokenizer;
/**
* 将Socket封装一个线程
*
* @author Administrator
*
*/
public class WeixinServerThread extends Thread {
public String ip;
public int port;
public InputStream in;
public BufferedReader reader;
public OutputStream out;
public PrintWriter writer;
public Socket socket;
public DataOutputStream dout;
public DataInputStream din;
public WeixinServerThread(Socket socket) {
super();
try {
this.socket = socket;
this.ip = socket.getInetAddress().getHostAddress();
this.port = socket.getPort();
// this.in = socket.getInputStream();
// this.reader = new BufferedReader(new InputStreamReader(in));
// this.out = socket.getOutputStream();
// this.writer = new PrintWriter(out);
this.din = new DataInputStream(socket.getInputStream());
this.dout = new DataOutputStream(socket.getOutputStream());
} catch (Exception e) {
e.printStackTrace();
}
// 启动
start();
}
/**
* 服务器端给客户端发送消息
*
* @param text
*/
public void sendMsg(String text) {
// writer.println(text);
// writer.flush();
try {
dout.writeUTF(text);
dout.flush();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Override
public void run() {
super.run();
// 服务器不断的读取客户端发送过来的消息
while (true) {
String content = null;
try {
// String content = reader.readLine();
content = din.readUTF();
if (content != null) {
StringTokenizer token = new StringTokenizer(content, "@");
String cmd = token.nextToken();
if ("text".equals(cmd)) {
System.out.println("服务器接收到消息:" + content);
// 转发给对方
String ip = token.nextToken();
int port = Integer.parseInt(token.nextToken());
String msgBody = token.nextToken();
System.out.println("转发给对方" + ip + "-----" + port + "----" + msgBody);
// 从在线用户中找到对应的消息接收者的Socket
// A->B ,找到B对应的Socket
for (WeixinServerThread oldSocket : Main.sockets) {
if (ip.equals(oldSocket.ip)&& port == oldSocket.port) {
// A的ip,因为B要知道是谁发送的
String text = "text@" + this.ip + "@"+ this.port + "@" + msgBody;
oldSocket.sendMsg(text);
System.out.println("对方收到--" + text);
break;
}
}
}
}
} catch (EOFException e) {
e.printStackTrace();
System.out.println("这是合法关闭的");
} catch (IOException e) {
e.printStackTrace();
try {
socket.close();
dout.close();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
}
@Override
public String toString() {
return "WeixinServerThread [ip=" + ip + ", port=" + port + "]";
}
}
客户端 :MainActivity.java
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView;
public class MainActivity extends Activity implements OnItemClickListener{
//所有在线的用户集合
public static final List<User> onlineUsers = new ArrayList<User>();
private ListView lv_users;
private UserAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
lv_users = (ListView) findViewById(R.id.lv_users);
adapter = new UserAdapter(this);
lv_users.setAdapter(adapter);
lv_users.setOnItemClickListener(this);
//注册广播接收者
MyWeixinReceiver receiver = new MyWeixinReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction("com.geekgroup.weixin.receiver");
registerReceiver(receiver, filter);
try {
//连接服务器
Socket socket = new Socket("192.168.10.44",9090);
WeixinClientThread thread = new WeixinClientThread(this,socket);
} catch (Exception e) {
e.printStackTrace();
}
}
//接收者
class MyWeixinReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
//刷新ListView数据
adapter.notifyDataSetChanged();
}
}
@Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
User user = (User) adapter.getItem(position);
Intent intent = new Intent(this,ChatActivity.class);
intent.putExtra("user", user);
startActivity(intent);
}
}
将客户中的Socket也封装成一个线程WeixinClientThread.java
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.StringTokenizer;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
/**
* 将Socket封装一个线程
* @author Administrator
*
*/
public class WeixinClientThread extends Thread{
public String ip;
public int port;
public InputStream in;
public BufferedReader reader;
public OutputStream out;
public PrintWriter writer;
public Socket socket;
public Context context;
public DataOutputStream dout;
public DataInputStream din;
public WeixinClientThread(Context context,Socket socket) {
super();
try {
instance = this;
this.context = context;
this.socket = socket;
this.ip = socket.getInetAddress().getHostAddress();
this.port = socket.getPort();
// this.in = socket.getInputStream();
// this.reader = new BufferedReader(new InputStreamReader(in));
// this.out = socket.getOutputStream();
// this.writer = new PrintWriter(out);
this.din=new DataInputStream(socket.getInputStream());
this.dout=new DataOutputStream(socket.getOutputStream());
} catch (Exception e) {
e.printStackTrace();
}
//启动
start();
}
private static WeixinClientThread instance;
public static WeixinClientThread getInstance(){
return instance;
}
/**
* 客户端给服务端发送消息
* @param text
*/
public void sendMsg(String text){
// writer.println(text);
// writer.flush();
try {
dout.writeUTF(text);
dout.flush();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Override
public void run() {
super.run();
//客户端不断的读取,服务器端发送过来的消息
while(true){
String content=null;
try {
// String content = reader.readLine();
content=din.readUTF();
Log.e("seaares", "客读服"+content);
if (content != null) {
//将字符串,根据@符号拆分
StringTokenizer token = new StringTokenizer(content, "@");
String cmd = token.nextToken();
//刷新用户列表
if (cmd.equals("refresh")) {
//ip
String ip = token.nextToken();
//port
int port = Integer.parseInt(token.nextToken());
//构造成用户
User user = new User(ip,port);
Log.e("seaares","用户"+ user.toString());
MainActivity.onlineUsers.add(user);
//发送广播,通知MainActivity在线用户列表发生数据更新
Intent intent = new Intent();
intent.setAction("com.geekgroup.weixin.receiver");
context.sendBroadcast(intent);
}else if (cmd.equals("text")) {
Log.d("seaares", "客户端接收到消息:"+content);
String ip = token.nextToken();
String port = token.nextToken();
String msgBody = token.nextToken();
//添加到消息集合
ChatActivity.messages.get(ip+"@"+port).add(msgBody);
//通知ListView刷新
Intent intent = new Intent();
intent.setAction("com.geekgroup.weixin.receiver.text");
context.sendBroadcast(intent);
}
}
} catch (Exception e) {
e.printStackTrace();
try {
socket.close();
dout.close();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
}
@Override
public String toString() {
return "WeixinClientThread [ip=" + ip + ", port=" + port + "]";
}
}
想要以上的 Demo 请到 http://download.youkuaiyun.com/detail/lx_yoyo/7697585 自行去下载