IPC 机制---使用Socket
Socket 也称套接字 ,是网络通信中的概念,它分为流式套接字 和用户数据报套接字 两种
Socket 也称套接字 ,是网络通信中的概念,它分为流式套接字 和用户数据报套接字 两种
流式套接字 :对应于传输控制层的TCP协议 TCP协议 是面向连接的协议,提供稳定的双向通信功能,TCP的连接需要经过三次握手才能完成,为了提供稳定的数据传输功能,其本身提供了超时重传机制,因此具有很高的稳定性。
用户数据报套接字:对应于传输控制层的UDP协议,UDP是无连接的,提供不稳定的单向通信功能,当然UDP也可以实现双向通信功能。在性能上UDP具有更好的效率,其缺点是不能保证数据一定能够正确传输,尤其是在网络拥塞的情况下。
使用 Socket 来进行通信首先需要声明权限
<uses-permission
android:name=
"android.permission.INTERNET"
/>
<uses-permission
android:name=
"android.permission.ACCESS_NETWORK_STATE"
/>
其次不能够在主线程中访问网络,因为这会导致我们的程序无法在Android4.0 以上的设备运行。而且进行网络操作很可能是耗时的,如果放在主线程的中,会影响程序的响应效率。
服务端代码:
public
class
TCPServerService
extends
Service {
private
boolean
mIsServiceDestoryed
=
false;
private
String[]
mDefinedMessages
=
new
String[] {
"浣犲ソ鍟婏紝鍝堝搱"
,
"璇烽棶浣犲彨浠�涔堝悕瀛楀憖锛�"
,
"浠婂ぉ鍖椾含澶╂皵涓嶉敊鍟婏紝shy"
,
"浣犵煡閬撳悧锛熸垜鍙槸鍙互鍜屽涓汉鍚屾椂鑱婂ぉ鐨勫摝"
,
"缁欎綘璁蹭釜绗戣瘽鍚э細鎹鐖辩瑧鐨勪汉杩愭皵涓嶄細澶樊锛屼笉鐭ラ亾鐪熷亣銆�"
};
@Override
public
void
onCreate() {
new
Thread(new
TcpServer()).start();
super.onCreate();
}
@Override
public
IBinder onBind(Intent intent) {
return
null
;
}
@Override
public
void
onDestroy() {
mIsServiceDestoryed
=
true
;
super.onDestroy();
}
private
class
TcpServer
implements
Runnable {
@SuppressWarnings("resource"
)
@Override
public
void
run() {
ServerSocket serverSocket =
null;
try
{
serverSocket =
new
ServerSocket(8688);
}
catch
(IOException e) {
System.
err.println("establish
tcp server failed, port:8688"
);
e.printStackTrace();
return;
}
while
(!mIsServiceDestoryed
) {
try
{
// 鎺ュ彈瀹㈡埛绔姹�
final
Socket client = serverSocket.accept();
System.
out.println("accept"
);
new
Thread() {
@Override
public
void
run() {
try
{
responseClient(client);
}
catch
(IOException e) {
e.printStackTrace();
}
};
}.start();
}
catch
(IOException e) {
e.printStackTrace();
}
}
}
}
private
void
responseClient(Socket client)
throws
IOException {
// 用于接收客户端消息
BufferedReader in =
new
BufferedReader(new
InputStreamReader(
client.getInputStream()));
// 用于向客户端发送消息
PrintWriter out =
new
PrintWriter(new
BufferedWriter(
new
OutputStreamWriter(client.getOutputStream())),
true);
out.println(
"娆㈣繋鏉ュ埌鑱婂ぉ瀹わ紒"
);
while
(!mIsServiceDestoryed
) {
String str = in.readLine();
System.
out.println("msg
from client:" + str);
if
(str ==
null
) {
//客户端断开连接
break;
}
int
i =
new
Random().nextInt(mDefinedMessages.
length);
String msg =
mDefinedMessages[i];
out.println(msg);
System.
out.println("send
:" + msg);
}
System.
out.println("client
quit." );
// 鍏抽棴娴�
MyUtils.
close(out);
MyUtils.
close(in);
client.close();
}
}
客户端代码:
public
class
TCPClientActivity
extends
Activity
implements
OnClickListener {
private
static
final
int
MESSAGE_RECEIVE_NEW_MSG
= 1;
private
static
final
int
MESSAGE_SOCKET_CONNECTED
= 2;
private
Button
mSendButton;
private
TextView
mMessageTextView;
private
EditText
mMessageEditText;
private
PrintWriter
mPrintWriter;
private
Socket
mClientSocket;
@SuppressLint(
"HandlerLeak")
private
Handler
mHandler
=
new
Handler() {
@Override
public
void
handleMessage(Message msg) {
switch
(msg.what
) {
case
MESSAGE_RECEIVE_NEW_MSG
: {
mMessageTextView.setText(mMessageTextView
.getText()
+ (String) msg.
obj);
break;
}
case
MESSAGE_SOCKET_CONNECTED
: {
mSendButton.setEnabled(true);
break;
}
default:
break;
}
}
};
@Override
protected
void
onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.
activity_tcpclient);
mMessageTextView
= (TextView) findViewById(R.id.msg_container);
mSendButton
= (Button) findViewById(R.id.send);
mSendButton.setOnClickListener(this);
mMessageEditText
= (EditText) findViewById(R.id.msg);
Intent service =
new
Intent(this
, TCPServerService.class);
startService(service);
new
Thread() {
@Override
public
void
run() {
connectTCPServer();
}
}.start();
}
@Override
protected
void
onDestroy() {
if
(mClientSocket
!=
null) {
try
{
mClientSocket.shutdownInput();
mClientSocket.close();
}
catch
(IOException e) {
e.printStackTrace();
}
}
super.onDestroy();
}
@Override
public
void
onClick(View v) {
if
(v ==
mSendButton
) {
final
String msg =
mMessageEditText
.getText().toString();
if
(!TextUtils.isEmpty(msg) &&
mPrintWriter
!=
null
) {
mPrintWriter.println(msg);
mMessageEditText.setText(""
);
String time = formatDateTime(System.
currentTimeMillis());
final
String showedMsg =
"self "
+ time +
":"
+ msg +
"\n";
mMessageTextView.setText(mMessageTextView
.getText() + showedMsg);
}
}
}
@SuppressLint(
"SimpleDateFormat")
private
String formatDateTime(
long
time) {
return
new
SimpleDateFormat("(HH:mm:ss)").format(
new
Date(time));
}
private
void
connectTCPServer() {
Socket socket =
null;
while
(socket ==
null) {
try
{
socket =
new
Socket("localhost"
, 8688);
mClientSocket
= socket;
mPrintWriter
=
new
PrintWriter(new
BufferedWriter(
new
OutputStreamWriter(socket.getOutputStream())),
true);
mHandler.sendEmptyMessage(
MESSAGE_SOCKET_CONNECTED);
System.
out.println("connect
server success"
);
}
catch
(IOException e) {
SystemClock.
sleep(1000);
System.
out.println("connect
tcp server failed, retry..."
);
}
}
try
{
// 鎺ユ敹鏈嶅姟鍣ㄧ鐨勬秷鎭�
BufferedReader br =
new
BufferedReader(new
InputStreamReader(
socket.getInputStream()));
while
(!TCPClientActivity.this.isFinishing())
{
String msg = br.readLine();
System.
out.println("receive
:" + msg);
if
(msg !=
null
) {
String time = formatDateTime(System.
currentTimeMillis());
final
String showedMsg =
"server "
+ time +
":"
+ msg
+
"\n";
mHandler.obtainMessage(
MESSAGE_RECEIVE_NEW_MSG, showedMsg)
.sendToTarget();
}
}
System.
out.println("quit..."
);
MyUtils.
close(mPrintWriter);
MyUtils.
close(br);
socket.close();
}
catch
(IOException e) {
e.printStackTrace();
}
}
}