Android Tcp操作
Tcp是基于傳輸層的面向連接的可靠通訊協(xié)議,其優(yōu)點(diǎn)是基于連接,使得服務(wù)端和客戶端可以實(shí)現(xiàn)雙向通信,且實(shí)時(shí)性高,在需要服務(wù)端主動(dòng)向客戶端推送數(shù)據(jù)的應(yīng)用場(chǎng)景中,使用TCP協(xié)議是一種很好的方式。
初學(xué)Android,將Android中Tcp的使用方式記錄一下,希望對(duì)新學(xué)Android開發(fā)的新同學(xué)有幫助,這里主要介紹TcpClient的使用,因?yàn)楹苌贂?huì)用Android來(lái)建立TcpServer端。
這里主要介紹Tcp客戶端的幾個(gè)應(yīng)用:
1.與服務(wù)器建立連接
2.向服務(wù)端發(fā)送數(shù)據(jù)
3.接收服務(wù)端返回的數(shù)據(jù)
4.斷線重連機(jī)制
?
在Android中使用socket有兩個(gè)地方需要注意的:
1.在AndroidMainfest.xml中需要添加對(duì)網(wǎng)絡(luò)的權(quán)限支持
<uses-permission android:name="android.permission.INTERNET" />2.Android中規(guī)定對(duì)socket的操作必須在線程中進(jìn)行,如在主線程中進(jìn)行操作會(huì)出現(xiàn)無(wú)法收發(fā)數(shù)據(jù)的情況。
?
(1)創(chuàng)建socket,與服務(wù)器建立連接
InetSocketAddress SerAddr = new InetSocketAddress(”192.168.1.100“,9988); //設(shè)置服務(wù)的IP地址和端口 try {socket.connect(SerAddr,3000); //嘗試連接服務(wù)器
}catch (Exception e){
}
(2)發(fā)送數(shù)據(jù)
/注意采用utf-8編碼確保中文傳輸不會(huì)亂碼 BufferedWriter bufferedWriter =new BufferedWriter(new OutputStreamWriter( socket.getOutputStream(),"utf-8")); bufferedWriter.write(”Hello“);
bufferedWriter.flush(); }catch (Exception e){
}
(3)接收數(shù)據(jù)
{ byte[] recData = new byte[inputStream.available()];
inputStream.read(recData); String iText=new String(recData,"utf-8");
?}
}catch (Exception e){}
(4)斷線重連
當(dāng)保持長(zhǎng)時(shí)間的連接時(shí),難免會(huì)因?yàn)榫W(wǎng)絡(luò)或其他原因?qū)е驴蛻舳伺c服務(wù)端斷開連接,所以代碼里面應(yīng)該定時(shí)的去檢查連接狀態(tài),當(dāng)連接斷開時(shí),
應(yīng)該重新嘗試連接服務(wù)端。我們這里可以使用socket.sendUrgentData(0xFF);函數(shù)來(lái)檢測(cè),當(dāng)服務(wù)端斷開時(shí),連續(xù)三次調(diào)用此函數(shù)會(huì)出現(xiàn)異常。
我們可以根據(jù)是否出現(xiàn)異常來(lái)斷定與服務(wù)器的連接情況。
try {socket.sendUrgentData(0xFF);
}catch (Exception e){
socket.close(); //關(guān)閉套接字,重新創(chuàng)建新的并調(diào)用connect函數(shù)重新連接
socket = new Socket();
}
以下貼出TcpHelper類的具體代碼:
public class TcpHelper{private Socket socket;
private BufferedWriter bufferedWriter;
private DataInputStream inputStream;
private boolean NeedStop;
private InetSocketAddress SerAddr;
public String ErrMsg;
private ReadThread readThread; //讀取數(shù)據(jù)線程
private OnReceiveEvent receiveEvent; //此事件用于當(dāng)接收到數(shù)據(jù)時(shí)向主線程通知接收到的數(shù)據(jù)
private long LastCheckTime;
public static interface OnReceiveEvent{
public void ReceiveBytes(byte[] iData);
public void ReceiveString(String iData);
}
public enum EDataType{EDT_BYTE,EDT_STRING};
private EDataType dataType;
public TcpHelper(String HostIp,int HostPort) {
try {
LastCheckTime=System.currentTimeMillis();
readThread =new ReadThread();
NeedStop=false;
SerAddr = new InetSocketAddress(HostIp,HostPort);
NeedStop=false;
socket = new Socket();
readThread.start();
}catch (Exception e)
{
ErrMsg=e.getMessage();
}
}
public void SendString(String iText){ //發(fā)送字符串
dataType=EDataType.EDT_STRING;
toSend(iText);
}
public void SendBytes(byte[] iBuf){ //發(fā)送字節(jié)流指令
dataType=EDataType.EDT_BYTE;
String iText = new String(iBuf);
toSend(iText);
}
//發(fā)送數(shù)據(jù)線程
private void toSend(final String iText){
new Thread(
new Runnable() {
@Override
public void run() {
try {
bufferedWriter.write(iText);
bufferedWriter.flush();
} catch (Exception e) {
}
}
}
).start();
}
public boolean isConnected(){
return socket.isConnected();
}
//設(shè)置通知事件
public void setReceiveEvent(OnReceiveEvent iEvent){
receiveEvent=iEvent;
}
//讀取線程
private class ReadThread extends Thread{
@Override
public void run() {
while (!NeedStop){
try {
if (!socket.isConnected() || socket.isClosed()){
socket.connect(SerAddr,3000);
if(bufferedWriter==null)
bufferedWriter =new BufferedWriter(new OutputStreamWriter( socket.getOutputStream(),"utf-8"));
if(inputStream==null)
inputStream = new DataInputStream(socket.getInputStream());
}
else {
if(inputStream.available()>0){
byte[] recData = new byte[inputStream.available()];
inputStream.read(recData);
if(receiveEvent!=null)
{
if(dataType==EDataType.EDT_BYTE) {
receiveEvent.ReceiveBytes(recData);
}
else {
String s=new String(recData,"utf-8");
receiveEvent.ReceiveString(s);
}
}
}
if (System.currentTimeMillis()-LastCheckTime>5000)
{
try {
LastCheckTime=System.currentTimeMillis();
socket.sendUrgentData(0xFF);
}catch (Exception e){
socket.close();
socket = new Socket();
bufferedWriter=null;
inputStream =null;
}
}
}
}catch (Exception e){
}
}
}
}
}
測(cè)試Tcp連接的Activity代碼:
import android.app.Activity;import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
public class TcpFormActivity extends Activity {
private TcpHelper tcpHelper;
private String SerIp;
private int SerPort;
private EditText InputMsg;
private TextView RecMsg;
private String TcpRecData;
private MyHandler handler;
private TcpReceive tcpReceive;
@Override
protected void onCreate(Bundle saveInstanceState){
super.onCreate(saveInstanceState);
setContentView(R.layout.activity_tcpform);
RecMsg = (TextView)findViewById(R.id.TVTcpData);
InputMsg = (EditText)findViewById(R.id.EdtTcpMsg);
}
public class TcpReceive implements TcpHelper.OnReceiveEvent{
public synchronized void ReceiveBytes(byte[] iData){
}
public synchronized void ReceiveString(String iData){
TcpRecData=iData;
Message msg=new Message();
msg.what=1;
handler.sendMessage(msg);
}
}
class MyHandler extends Handler {
public MyHandler() {
}
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case 1:
RecMsg.append(TcpRecData); //接收到數(shù)據(jù)顯示到TextView上
break;
}
super.handleMessage(msg);
}
}
public void onConnectClick(View view){
if(tcpHelper==null)
{
SerIp = ((EditText)findViewById(R.id.EdtTcpSerIp)).getText().toString();
SerPort =Integer.parseInt(((TextView)findViewById(R.id.EdtTcpPort)).getText().toString());
tcpHelper = new TcpHelper(SerIp,SerPort);
tcpReceive = new TcpReceive();
tcpHelper.setReceiveEvent(tcpReceive);
handler = new MyHandler();
}
}
public void onSendMsgClick(View view){
try {
String iText=InputMsg.getText().toString();
tcpHelper.SendString(iText);
}catch (Exception e)
{
}
}
} ?
?
轉(zhuǎn)載于:https://www.cnblogs.com/WushiShengFei/p/7397947.html
總結(jié)
以上是生活随笔為你收集整理的Android Tcp操作的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: hdu 6148 数位dp
- 下一篇: 实战c++中的vector系列--vec