Android socket与服务器通信长连接通信

时间:2022-10-22 17:58:59

近期因项目需要用到Socket通信,实现客户端Socket 与 服务器通信。实现客户端发送信息--》服务器接收信息---》服务器返回信息--》客户端接收返回信息的长连接通讯,已测试通过。

    服务端代码:

    

package com.cj.socket;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;

public class Server extends Thread{
private ServerSocket serverSocket = null;
private int port = 8142;

@Override
public void run() {
try {
serverSocket = new ServerSocket(port);
System.out.println("server builded.....");
OutputStream out = null;
InputStream in = null;
while(true){
Socket socket = serverSocket.accept();
try{
in = socket.getInputStream();
out = socket.getOutputStream();
while(true){
String reciverData = readFromInputStream(in);
System.out.println(reciverData);
reciverData = "已接收--》\n" + reciverData;
writeToClient(out, reciverData);
}
}catch(Exception e){
e.printStackTrace();
}finally{
in.close();
out.close();
}
//BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);
//String a = null;
//String b= null;
//while((a = in.readLine()) != null){
//b += a;
//System.out.println(a);
//out.println("已接收。。。。。" + a);
//out.flush();
//}

}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
try {
serverSocket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
};
}
}

public String readFromInputStream(InputStream in){
int count = 0;
byte[] inDatas = null;
try{
while(count == 0){
count = in.available();
}
inDatas = new byte[count];
in.read(inDatas);
return new String(inDatas);
}catch(Exception e){
e.printStackTrace();
}
return null;
}

public void writeToClient(OutputStream out, String data){
try{
out.write(data.getBytes());
out.flush();
}catch(Exception e){
e.printStackTrace();
}
}
}


package com.cj.socket;

public class Test {
public static void main(String[] argv){
new Server().start();
}
}

    客户端代码:

package com.cj.testsocket.socket;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.LinkedList;
import java.util.List;

import android.util.Log;

public class ClientSocket extends Thread{
public static final String SOCKET_TAG = "socketTag";
public static final long HEART_TIME = 10000;
public static final long SEND_TIME = 1000;
private static final String HEART_MSG = "heart";
/**
* 接收线程
*/
private Thread mReciverThread = null;

/**
* 心跳时间
*/
private long mHeartTime = 0;

/**
* client socket
*/
private Socket mSocket = null;

private InputStream in = null;

private OutputStream out = null;

/**
* 主机IP地址
*/
private String serverUrl = null;

/**
* 主机端口
*/
private int serverPort = 0;

/**
* 消息队列
*/
private volatile List<String> mMsgQueue = null;

/**
* 接收到服务端返回信息回调接口
*/
private OnSocketRecieveCallBack mOnSocketRecieveCallBack;

/*********************************************
*
* gettter or setter
*
********************************************/
public Socket getSocket() {
return mSocket;
}

public String getServerUrl() {
return serverUrl;
}

public void setServerUrl(String serverUrl) {
this.serverUrl = serverUrl;
}

public int getServerPort() {
return serverPort;
}

public void setServerPort(int serverPort) {
this.serverPort = serverPort;
}

public List<String> getMsgQueue() {
return mMsgQueue;
}

public void setMsgQueue(List<String> mMsgQueue) {
this.mMsgQueue = mMsgQueue;
}

public OnSocketRecieveCallBack getOnSocketRecieveCallBack() {
return mOnSocketRecieveCallBack;
}

public void setOnSocketRecieveCallBack(OnSocketRecieveCallBack mOnSocketRecieveCallBack) {
this.mOnSocketRecieveCallBack = mOnSocketRecieveCallBack;
}

/**
* 构造函数
*/
public ClientSocket(String hostName, int port){
serverUrl = hostName;
serverPort = port;
mMsgQueue = new LinkedList<String>();

mReciverThread = new Thread(){
@Override
public void run(){
while(!this.isInterrupted()){
reciverMsgFromServer();
}
}
};
mReciverThread.start();
}

/***********************************************
*
* Methods
*
**********************************************/
public String readFromInputStream(InputStream in){
int count = 0;
byte[] inDatas = null;
try{
while(count == 0){
count = in.available();
}
inDatas = new byte[count];
in.read(inDatas);
return new String(inDatas);
}catch(Exception e){
e.printStackTrace();
}
return null;
}

private void reciverMsgFromServer(){
// 接收数据
if(mSocket != null && mSocket.isConnected() && !mSocket.isInputShutdown() && in != null){
try {
String recieveMsg = readFromInputStream(in);
if(mOnSocketRecieveCallBack != null)
mOnSocketRecieveCallBack.OnRecieveFromServerMsg(recieveMsg);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

/**
* 发送心跳包
*/
public void sendHeart(String msgHeart){
((LinkedList<String>)mMsgQueue).addFirst(msgHeart);
}

/**
* socket 是否有断开连接
* @return
*/
public boolean isSocketConnected(){
if(mSocket != null && mSocket.isConnected()) return true;
return false;
}
/**
* 添加发送消息到队列
* @param msg
*/
public void addSendMsgToQueue(String msg){
mMsgQueue.add(msg);
}

/**
* 判断消息队列是否为空
* @return
*/
public boolean isMsgQueueEmpty(){
return mMsgQueue.isEmpty();
}

@Override
public void run() {
InetAddress inetAddress = null;
try {
mSocket = new Socket(InetAddress.getByName(serverUrl), serverPort);
in = mSocket.getInputStream();
out = mSocket.getOutputStream();
mHeartTime = System.currentTimeMillis();
Log.v(SOCKET_TAG, "client socket create successed");
// 轮询发送消息列表中的数据
while(true){
// 判断是否要发送心跳包
if(Math.abs(mHeartTime - System.currentTimeMillis()) > HEART_TIME) sendHeart(HEART_MSG);

Thread.sleep(SEND_TIME);
// 判断client socket 是否连接上Server
if(mSocket.isConnected()){
Log.v(SOCKET_TAG, "### client socket connected ###");
// 发送数据
if(!mSocket.isOutputShutdown() && !isMsgQueueEmpty()){
out.write(mMsgQueue.get(0).getBytes());
Log.v(SOCKET_TAG, "sned msg toServer: " + mMsgQueue.get(0));
Log.v(SOCKET_TAG, "## msg count : " + mMsgQueue.size());
// 将发送过的数据移除消息列表
mMsgQueue.remove(0);
mHeartTime = System.currentTimeMillis();
}
}else{
// 重建连接
Log.v(SOCKET_TAG, "client socket disconnected");
if(!mSocket.isClosed()) mSocket.close();
inetAddress = InetAddress.getByName(serverUrl);
mSocket = new Socket(inetAddress, serverPort);
}
}
}catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Log.v(SOCKET_TAG,e.getMessage());
} catch (UnknownHostException e) {
e.printStackTrace();
Log.v(SOCKET_TAG,e.getMessage());
} catch (IOException e) {
e.printStackTrace();
Log.v(SOCKET_TAG,e.getMessage());
}finally{
if(out != null)
try {
out.close();
} catch (IOException e2) {
// TODO Auto-generated catch block
e2.printStackTrace();
}
if(in != null){
try {
in.close();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}

if(mSocket != null){
try {
mSocket.close();
} catch (IOException e) {
e.printStackTrace();
Log.v(SOCKET_TAG,e.getMessage());
}
}
Log.v(SOCKET_TAG, "client socket close");
}
}

@Override
protected void finalize() throws Throwable {
super.finalize();
if(mReciverThread != null && !mReciverThread.isInterrupted()){
mReciverThread.interrupt();
mReciverThread = null;
}

if(mSocket != null && !mSocket.isClosed()){
mSocket.close();
}
Log.v(SOCKET_TAG, "client socket destory");
}

/**
* 接收到服务端返回信息回调接口
* @author Administrator
*
*/
public interface OnSocketRecieveCallBack{
public void OnRecieveFromServerMsg(String msg);
}
}


package com.cj.testsocket;import java.util.ArrayList;import java.util.List;import android.app.Activity;import android.os.Bundle;import android.os.Handler;import android.os.Message;import android.view.View;import android.view.View.OnClickListener;import android.widget.ArrayAdapter;import android.widget.Button;import android.widget.EditText;import android.widget.ListView;import com.cj.testsocket.socket.ClientSocket;import com.cj.testsocket.socket.ClientSocket.OnSocketRecieveCallBack;public class MainActivity extends Activity implements OnClickListener, OnSocketRecieveCallBack{public static final String SERVER_NAME = "192.168.0.119";public static final int PORT = 8142;Button btn_send;EditText ed_send;ListView mListView;ArrayAdapter<String> arryAdapter = null;List<String> mDatas = null;Handler mHandler = new Handler(){@Overridepublic void handleMessage(Message msg) {// TODO Auto-generated method stubmDatas.add((String)msg.obj);arryAdapter.notifyDataSetChanged();}};ClientSocket mClientSocket = null;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);mDatas = new ArrayList<String>();mDatas.add("Hello world");arryAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, mDatas);ed_send = (EditText)this.findViewById(R.id.et_send);btn_send = (Button)this.findViewById(R.id.btn_send);btn_send.setOnClickListener(this);mListView = (ListView)this.findViewById(R.id.list);mListView.setAdapter(arryAdapter);mClientSocket = new ClientSocket(SERVER_NAME, PORT);mClientSocket.setOnSocketRecieveCallBack(this);mClientSocket.start();}@Overridepublic void onClick(View v) {// TODO Auto-generated method stubString msg = ed_send.getText().toString();if(msg != null && mClientSocket.isSocketConnected()){mClientSocket.addSendMsgToQueue(msg);mDatas.add(msg);arryAdapter.notifyDataSetChanged();ed_send.setText("");}}@Overridepublic void OnRecieveFromServerMsg(String msg) {// TODO Auto-generated method stubif(msg != null){Message message = Message.obtain();message.obj = msg;mHandler.sendMessage(message);}}}

    布局文件:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    tools:context=".MainActivity" >    <ListView        android:id="@+id/list"        android:layout_width="fill_parent"        android:layout_height="wrap_content"        android:listSelector="@android:color/transparent"        android:transcriptMode="alwaysScroll"        android:stackFromBottom="true"/>    <LinearLayout        android:layout_width="fill_parent"        android:layout_height="48dp"        android:layout_alignParentBottom="true"        android:background="#818080"        android:orientation="horizontal" >        <EditText            android:id="@+id/et_send"            android:background="#ffffff"            android:layout_margin="4dp"            android:layout_width="0dp"            android:layout_height="fill_parent"            android:layout_weight="5"             android:hint="请输入要发送的信息"/>        <Button            android:id="@+id/btn_send"            android:background="@drawable/btn_send_selector"            android:layout_margin="4dp"            android:layout_width="0dp"            android:layout_height="fill_parent"            android:layout_weight="2"            android:text="发  送" />    </LinearLayout></RelativeLayout>


AndroidManifest.xml


<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android"    package="com.cj.testsocket"    android:versionCode="1"    android:versionName="1.0" >    <uses-sdk        android:minSdkVersion="8"        android:targetSdkVersion="18" />    <uses-permission android:name="android.permission.INTERNET"/>    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>    <application        android:allowBackup="true"        android:icon="@drawable/ic_launcher"        android:label="@string/app_name"        android:theme="@style/AppTheme" >        <activity            android:name="com.cj.testsocket.MainActivity"            android:label="@string/app_name" >            <intent-filter>                <action android:name="android.intent.action.MAIN" />                <category android:name="android.intent.category.LAUNCHER" />            </intent-filter>        </activity>    </application></manifest>