Socket通信的原理

大家好:
    这是我第一次写微博,写的不好之处请留言告知,谢谢。下面就来谈谈我对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.csdn.net/detail/lx_yoyo/7697585 自行去下载
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值