前言
这段时间做的东西比较杂,但是对学习来说还是很有帮助的,这次做的基于socket的即时通讯也是为了更加了解IM,本来是打算使用openfire或者apollo服务器来实现的,但是中途时间上的问题,临时改了需求,后期的语音通话还是要借助第三方服务器的,这里主要是自己用myeclipse写了一个简单的代理服务器,主要是将客户端发来的消息转发到已经保存到链表中的socket中,实现比较简单,主要是解决发送图片的模块,我参考了很多文章,但是大多写的都不是很全,故自己写了一下,[socket即时通讯源码](https://github.com/firesmog/MyGreenDao),写这篇博客,一是为了记录自己的学习进度,而是希望能给正在学习路上的各位同学一点点帮助。
服务端介绍
这里的服务端是采用myeclipse写的,比较简单单,主要负责将任意客户端传过来的消息的进行转发,然后使得客户端收到信息后能在自己的界面上进行展示,具体代码如下,仅供参考。
public class tcpservice {
private static final int SERVERPORT = 8090;
private static List<Socket> mClientList = new ArrayList<Socket>();
private ExecutorService mExecutorService;
private ServerSocket mServerSocket;
public static void main(String[] args) {
new tcpservice();
}
public tcpservice() {
try {
//服务端套接字,这里给定客户端要连接的目标端口即可
mServerSocket = new ServerSocket(SERVERPORT);
//使用线程池,来一个客户端,开一个线程处理
mExecutorService = Executors.newCachedThreadPool();
System.out.println("start...");
Socket client = null;
while (true) {
//监听客户端的连接,一旦客户端连接上,则将客户端套接字赋值给client
client = mServerSocket.accept();
//在链表中保存客户端,以便后面的消息转发
mClientList.add(client);
System.out.println(client.toString());
//开启线程
mExecutorService.execute(new ThreadServer(client));
}
}
catch (IOException e) {
e.printStackTrace();
}
}
//新建自己的线程类,实现线程内run方法的实现
static class ThreadServer implements Runnable {
private Socket mSocket;
private BufferedReader mBufferedReader;
private PrintWriter mPrintWriter;
private String mStrMSG;
//构造方法,将客户端套接字socket传进来
public ThreadServer(Socket socket) throws IOException {
this.mSocket = socket;
//获得客户端输入流,用于读取客户端数据
mBufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
mStrMSG = "user:"+this.mSocket.getInetAddress()+" come total:" + mClientList.size();
}
//run方法的实现
public void run() {
try {
//判断客户端发送过来的信息是否是要退出聊天
while ((mStrMSG = mBufferedReader.readLine()) != null) {
if (mStrMSG.trim().equals("exit")) {
mClientList.remove(mSocket);
mBufferedReader.close();
mPrintWriter.close();
mStrMSG = "user:"+this.mSocket.getInetAddress()+" exit total:" + mClientList.size();
mSocket.close();
sendMessage();
break;
}
else {
// mStrMSG = mSocket.getInetAddress() + ":" + mStrMSG;
System.out.println( mStrMSG);
sendMessage();
}
}
}
catch (IOException e) {
e.printStackTrace();
}
}
private void sendMessage() throws IOException {
System.out.println(mStrMSG);
//遍历所有的客户端套接字,将消息转发出去
for (Socket client : mClientList) {
mPrintWriter = new PrintWriter(client.getOutputStream(), true);
mPrintWriter.println(mStrMSG);
mPrintWriter.flush();
}
}
}
}
服务端就介绍到,这里,因为实现比较简单,所以也不多做赘述。
客户端介绍
这里的客户端实在Androidstudio上实现的,逻辑不难,主要是界面上的操作,大家可以参考一下。这里先贴出界面图,比较丑陋,大家见谅。
主界面主要采用的ViewPger+Recycleview,发送表情主要是采用Recycleview+girdView+EditText,,下面写给出主界面布局,以及聊天界面布局,大家仅参考,具体内容,数据资源都在源码中,大家自行下载。
//主界面
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_main"
android:layout_width="match_parent" android:layout_height="match_parent"
android:orientation="vertical"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="example.com.myapplication.MainActivity">
<example.com.myapplication.MyViewPager.MyViewPager
android:id="@+id/vp_main"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" >
android:persistentDrawingCache="animation"
</example.com.myapplication.MyViewPager.MyViewPager>
<RadioGroup
android:id="@+id/rd_group"
android:layout_width="match_parent"
android:layout_height="90dp"
android:layout_alignParentBottom="true"
android:orientation="horizontal">
<RadioButton
android:id="@+id/rd_1"
style="@style/tab_menu_item"
android:drawableTop="@drawable/message"
android:text="消息"/>
<RadioButton
android:id="@+id/rd_2"
style="@style/tab_menu_item"
android:drawableTop="@drawable/contactor"
android:text="联系人"/>