转载请注明本文出自Cym的博客(http://blog.csdn.net/cym492224103),谢谢支持!
山寨版微信(上)
即时通信
我们使用了Socket编程(套接字编程)
服务器
创建ServerSocket
等待客户端的连接
Socket s =ss.qccpet();
客户端
Soket s = new Socket();
原理图:
服务端:
Server
public class Server {
// 记录所有的客户端
private List<ThreadClient> list = new ArrayList<ThreadClient>();
// 启动服务器
public void start() throws Exception {
// 创建一个服务器
final ServerSocket serverSocket = new ServerSocket(8809);
System.out.println(serverSocket.getLocalPort());
System.out.println(serverSocket.getInetAddress().getHostAddress());
// 开线程去反馈给用户的信息
new Thread(new Runnable() {
@Override
public void run() {
// 开启循环接受客服端反馈的信息
while (true) {
try {
// 得到客户端反馈的信息
Socket socket =serverSocket.accept();
// 取出客户的信息
ThreadClient client = new ThreadClient(socket);
System.out.println("ip:"+client.ip+",port:"+client.port);
/**自定义通信协议
* 服务器通知用户刷新列表,
* 用户上线 refresh:
* 关键字 name:上线的ip地址
* port:上线的端口
* refresh@name@port
*/
// 告诉别人我上线了
// 通知之前上线的人
/**
* 迭代所有客户端:发送消息给每一个客户端
* c:之前上线的用户(别人)
*/
for (ThreadClient c : list) {
String msg = "refresh@" +client.ip+ "@" +client.port;
c.sendMessge(msg);
}
// 上线后得到上线的人
// 自己上线之后,也要知道之前上线的人
for (ThreadClient c : list) {
String msg = "refresh@" +c.ip+ "@" +c.port;
client.sendMessge(msg);
}
list.add(client);
} catch (Exception e) {
// TODO: handle exception
}
}
}
}).start();
}
public static void main(String[] args) {
Server server = new Server();
try {
server.start();
} catch (Exception e) {
// TODO Auto-generated catchblock
e.printStackTrace();
System.out.println("启动失败");
}
}
}
ThreadClient:
Socket详细信息
// 用户相信信息
public class ThreadClient extends Thread {
// ip 地址
public String ip;
// 端口号
public int port;
// 客户端套接字
public Socket socket;
// 字节输入流
public InputStream is;
// 字节输出流
public OutputStream os;
// 字符打印流
public PrintWriter pw;
// 字符缓存流
public BufferedReader br;
public ThreadClient(Socketsocket){
try {
this.socket = socket;
this.port = socket.getPort();
this.ip =socket.getInetAddress().getHostAddress();
this.is = socket.getInputStream();
this.os =socket.getOutputStream();
this.br = new BufferedReader(new InputStreamReader(is));
this.pw = new PrintWriter(os);
} catch (Exception e) {
// TODO: handle exception
}
}
// 向客户端发送消息的方法
public void sendMessge(String msg)
{
pw.println(msg);
pw.flush();
} @Override
public void run() {
// TODO Auto-generated method stub
super.run();
}
}
客户端:
Adapter:
public class MyAdapter extends BaseAdapter {
private List<UserInfo> infos;
private Context context;
private LayoutInflater mInflater;
publicMyAdapter(List<UserInfo> infos,Context context){
this.infos = infos;
this.context = context;
mInflater = LayoutInflater.from(context);
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return infos.size();
}
@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return infos.get(position);
}
@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
View view = null;
ViewHodler hodler = null;
if(convertView!=null){
view = convertView;
hodler = (ViewHodler) view.getTag();
}else
{
view = mInflater.inflate(R.layout.item, null);
hodler = new ViewHodler();
hodler.tv_ip = (TextView) view.findViewById(R.id.tv_ip);
hodler.tv_port = (TextView)view.findViewById(R.id.tv_port);
hodler.tv_isnew = (TextView) view.findViewById(R.id.tv_isnew);
view.setTag(hodler);
}
// 得到数据
UserInfo info = infos.get(position);
hodler.tv_ip.setText(info.ip);
hodler.tv_port.setText(info.port+"");
return view;
}
private class ViewHodler{
TextView tv_ip;
TextView tv_port;
TextView tv_isnew;
}
}
Client:
public class ThreadClient extends Thread {
public List<UserInfo> userInfos= new ArrayList<UserInfo>();
public Socket socket;
public String ip;
public int port;
public InputStream is;
public OutputStream os;
public PrintWriter pw;
public BufferedReader br;
public static Context context;
private static ThreadClient threadClient;
public synchronized static ThreadClient getThreadClient(Context c){
context = c;
if(threadClient == null){
try {
//创建Socket
Socket socket = new Socket("192.168.16.2", 8809);
threadClient = new ThreadClient(socket);
threadClient.start();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return threadClient;
}
private ThreadClient(Socketsocket){
this.socket = socket;
this.ip = socket.getInetAddress().getHostAddress();
this.port = socket.getPort();
try {
this.is = socket.getInputStream();
this.os =socket.getOutputStream();
this.pw = new PrintWriter(os);
this.br = new BufferedReader(new InputStreamReader(is));
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void run() {
super.run();
while(true){
try {
String message = br.readLine();
if(message!=null)
{
//StringTokenizer 用户截取有规律符号的字符串的
StringTokenizer token = new StringTokenizer(message,"@");
String msg = token.nextToken();
// 判断是否是上线通知
if("refresh".equals(msg))
{
String ip1 =token.nextToken();
int port1 = Integer.parseInt(token.nextToken());
// 发送广播刷新列表
如果不是自己上线就发送广播刷新用户列表
boolean flag = this.ip.equals(ip1)&&this.port == port1;
if(!flag){
userInfos.add(new UserInfo(ip1, port1));
Intent intent = new Intent();
intent.setAction("com.cym.MainActivity");
context.sendBroadcast(intent);
}
}
}
} catch (Exception e) {
// TODO: handle exception
}
}
}
}
Domain:
public class UserInfo {
public String ip;
public int port;
public boolean isNew;
public UserInfo(String ip, int port) {
super();
this.ip = ip;
this.port = port;
}
}
Ui:
public class MainActivity extends Activity {
private ListView lv_user;
private MyAdapter adapter;
private MyRefreshBroadCastReceiverreceiver;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
lv_user = (ListView) findViewById(R.id.lv_user);
// 客户端
ThreadClient threadClient = ThreadClient.getThreadClient(this);
List<UserInfo> userInfos =threadClient.userInfos;
adapter = new MyAdapter(userInfos, this);
lv_user.setAdapter(adapter);
receiver = new MyRefreshBroadCastReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction("com.cym.MainActivity");
registerReceiver(receiver, filter);
}
private class MyRefreshBroadCastReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context,Intent intent) {
// TODO Auto-generated methodstub
adapter.notifyDataSetChanged();
}
}
}