您的位置:首页 > 其它

基于安卓4.4的socket通信——文字聊天

2014-03-06 17:03 302 查看
学习了3个月安卓了,今天开始写点东西。

这个安卓的聊天demo,还是分为客户端、服务器两大部分,先来看看客户端:

界面代码如下:

protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
init();
//打开应用就默认连接
cHandler.sendEmptyMessage(0x01);
}

private void init() {
cButtonSend = (Button) findViewById(R.id.btn);
cName = (EditText) findViewById(R.id.yhm);
cToName = (EditText) findViewById(R.id.jsm);
cEditTextContent = (EditText) findViewById(R.id.et);

cList = (ListView) findViewById(R.id.listview);

mAdapter = new ChatMsgViewAdapter(this, mDataArrays);
cList.setAdapter(mAdapter);
cButtonSend.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View v) {
if( cName.getText().toString().equals("") || cName.getText().toString()==null || cToName.getText().toString().equals("") ||
cToName.getText().toString()==null || cEditTextContent.getText().toString().equals("") || cEditTextContent.getText().toString()==null){

new AlertDialog.Builder(
MainActivity.this)
.setTitle("")
.setMessage("请填写完整!")
.setPositiveButton("确定", null).show();
}else{
//发送信息展现
ChatMsgEntity entity = new ChatMsgEntity();
entity.setDate(getDate());
entity.setName(cName.getText().toString());
entity.setMsgType(false);
entity.setText(cEditTextContent.getText().toString());

mDataArrays.add(entity);
mAdapter.notifyDataSetChanged();
cList.setSelection(cList.getCount() - 1);

cHandler.sendEmptyMessage(0x01);

//清楚输入框内容
cEditTextContent.setText("");
}
}
});

}
socket相关代码:

Handler cHandler = new Handler() {

@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case 0x01:
cThread = new Thread() {
@Override
public void run() {
super.run();
DataInputStream dis = null;
DataOutputStream dos = null;
try {

// 阻塞函数,正常连接后才会向下继续执行
cSocket = new Socket(ADDRESS, PORT);
dis = new DataInputStream(cSocket.getInputStream());
dos = new DataOutputStream(cSocket.getOutputStream());

if(mDataArrays.isEmpty()){//刚打开应用,只是建立连接
}else{
// 向服务器写数据
ChatMsgEntity e = new ChatMsgEntity();
e = mDataArrays.get(mDataArrays.size()-1);

dos.writeUTF(e.getName());
dos.writeUTF(cToName.getText().toString());
dos.writeUTF(e.getText().toString());

// 读取服务器发来的数据
//cContent += dis.readUTF();
recive1 = dis.readUTF();
recive2 = dis.readUTF();
if(recive1.equals("错误*001\n我不在线")){
//对方不在线,发送失败
cHandler.sendEmptyMessage(0x03);
}else{
//接收信息展现
cHandler.sendEmptyMessage(0x04);
}

}

} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (dis == null) {
dis.close();
}
if (dos == null) {
dos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
//							cHandler.sendEmptyMessage(0x02);
}
}

};
cThread.start();
break;
case 0x02:
//				cTextViewContent.setText(cContent);
break;
case 0x03://对方不在线,发送失败
recive(recive2, recive1);
break;
case 0x04://接收信息展现
recive(recive1, recive2);
break;

default:
break;
}
}

};


下面是接收服务端返回的消息(包括他人发送给你,和你发送消息,但是对方不在线返回的消息)

其中关键是修改界面必须要在主线程中完成:mAdapter.notifyDataSetChanged();

public void recive(String a, String b){
ChatMsgEntity e = new ChatMsgEntity();
e.setName(a);
e.setMsgType(true);
e.setText(b);
e.setDate(getDate());
mDataArrays.add(e);

mAdapter.notifyDataSetChanged();
cList.setSelection(cList.getCount() - 1);
}

最后不要忘了配置相关权限,

<!-- 添加联网权限 -->
<uses-permission android:name="android.permission.INTERNET" />


接下去看服务端代码:

public class MultiThreadServer {
private int port=8888;
private ServerSocket serverSocket;
private static ExecutorService executorService;//线程池
private final int POOL_SIZE=10;//单个CPU线程池大小
static HashMap<String, Socket> map=new HashMap<String, Socket>();//保存链接

public MultiThreadServer() throws IOException{
serverSocket=new ServerSocket(port);
//Runtime的availableProcessor()方法返回当前系统的CPU数目.
setExecutorService(Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()*POOL_SIZE));
System.out.println("服务器启动");
}

public void service(){
while(true){
Socket socket=null;
try {
//接收客户连接,只要客户进行了连接,就会触发accept();从而建立连接
socket=serverSocket.accept();
getExecutorService().execute(new Handler(socket));

} catch (Exception e) {
e.printStackTrace();
}
}
}

public static void main(String[] args) throws IOException {
new MultiThreadServer().service();
}

public static ExecutorService getExecutorService() {
return executorService;
}

public void setExecutorService(ExecutorService executorService) {
MultiThreadServer.executorService = executorService;
}

}

class Handler implements Runnable{
private Socket socket;
public Handler(Socket socket){
this.socket=socket;
}

public void run(){

DataInputStream dis = null;
DataOutputStream dos = null;
try {
while (true) {
System.out.println("正在等待客户连接...");
// 这里处于等待状态,如果没有客户端连接,程序不会向下执行
dis = new DataInputStream(socket.getInputStream());
dos = new DataOutputStream(socket.getOutputStream());
// 读取数据
String fp = dis.readUTF();
String tp = dis.readUTF();

String clientStr = dis.readUTF();

System.out.println("---客户端已成功连接---");

MultiThreadServer.map.put(fp, socket);
// 得到客户端的IP
System.out.println("客户端的IP=" + socket.getInetAddress());
// 得到客户端的端口号
System.out.println("客户端的端口号=" + socket.getPort());
// 得到本地端口号
System.out.println("本地服务器端口号=" + socket.getLocalPort());
System.out.println("信息:" + fp +"对"+ tp +"说:"+ clientStr);
System.out.println("---------------------------------");

//判断接收方 是否在线
if(MultiThreadServer.map.containsKey(tp)){
Socket socket1=MultiThreadServer.map.get(tp);
DataOutputStream out=new DataOutputStream(socket1.getOutputStream());
out.writeUTF(fp);
out.writeUTF(clientStr);
out.flush();
}else{
// 写出数据
dos.writeUTF("错误*001\n我不在线");
dos.writeUTF(tp);
}

//消息转发不能新建一个socket,原来端口被占用 会报错
//				MultiThreadServer.getExecutorService().execute(new Handler1(socket.getInetAddress().toString(),socket.getPort(),clientStr,fp));
}
}catch (EOFException e) {
System.out.println("这是合法的,客户端连接已断开");
}catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (dis != null) {
dis.close();
}
if (dos != null) {
dos.close();
}
//				 if(socket!=null){
//					 socket.close();
//				 }

} catch (IOException e) {
e.printStackTrace();
}

}

}
}


下面看一下运行效果:



如上图,是自己发送消息给自己,下图为发送给别人。



安卓文本聊天的至此完结,虽然还有很多不足,以后有机会再改了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: