Android开发之Socket通信传输简单示例
本文实例讲述了AndroidSocket通信传输实现方法。分享给大家供大家参考,具体如下:
1.开篇简介
Socket本质上就是Java封装了传输层上的TCP协议(注:UDP用的是DatagramSocket类)。要实现Socket的传输,需要构建客户端和服务器端。另外,传输的数据可以是字符串和字节。字符串传输主要用于简单的应用,比较复杂的应用(比如Java和C++进行通信),往往需要构建自己的应用层规则(类似于应用层协议),并用字节来传输。
2.基于字符串传输的Socket案例
1)服务器端代码(基于控制台的应用程序,模拟)
importjava.io.BufferedReader;
importjava.io.BufferedWriter;
importjava.io.IOException;
importjava.io.InputStreamReader;
importjava.io.OutputStreamWriter;
importjava.io.PrintWriter;
importjava.net.ServerSocket;
importjava.net.Socket;
importjava.util.ArrayList;
importjava.util.List;
importjava.util.concurrent.ExecutorService;
importjava.util.concurrent.Executors;
publicclassMain{
privatestaticfinalintPORT=9999;
privateListmList=newArrayList();
privateServerSocketserver=null;
privateExecutorServicemExecutorService=null;//threadpool
publicstaticvoidmain(String[]args){
newMain();
}
publicMain(){
try{
server=newServerSocket(PORT);
mExecutorService=Executors.newCachedThreadPool();//createathreadpool
System.out.println("服务器已启动...");
Socketclient=null;
while(true){
client=server.accept();
//把客户端放入客户端集合中
mList.add(client);
mExecutorService.execute(newService(client));//startanewthreadtohandletheconnection
}
}catch(Exceptione){
e.printStackTrace();
}
}
classServiceimplementsRunnable{
privateSocketsocket;
privateBufferedReaderin=null;
privateStringmsg="";
publicService(Socketsocket){
this.socket=socket;
try{
in=newBufferedReader(newInputStreamReader(socket.getInputStream()));
//客户端只要一连到服务器,便向客户端发送下面的信息。
msg="服务器地址:"+this.socket.getInetAddress()+"cometoal:"
+mList.size()+"(服务器发送)";
this.sendmsg();
}catch(IOExceptione){
e.printStackTrace();
}
}
@Override
publicvoidrun(){
try{
while(true){
if((msg=in.readLine())!=null){
//当客户端发送的信息为:exit时,关闭连接
if(msg.equals("exit")){
System.out.println("ssssssss");
mList.remove(socket);
in.close();
msg="user:"+socket.getInetAddress()
+"exittotal:"+mList.size();
socket.close();
this.sendmsg();
break;
//接收客户端发过来的信息msg,然后发送给客户端。
}else{
msg=socket.getInetAddress()+":"+msg+"(服务器发送)";
this.sendmsg();
}
}
}
}catch(Exceptione){
e.printStackTrace();
}
}
/**
*循环遍历客户端集合,给每个客户端都发送信息。
*/
publicvoidsendmsg(){
System.out.println(msg);
intnum=mList.size();
for(intindex=0;index
2)Android客户端代码
packagecom.amaker.socket;
importjava.io.BufferedReader;
importjava.io.BufferedWriter;
importjava.io.IOException;
importjava.io.InputStreamReader;
importjava.io.OutputStreamWriter;
importjava.io.PrintWriter;
importjava.net.Socket;
importandroid.app.Activity;
importandroid.app.AlertDialog;
importandroid.content.DialogInterface;
importandroid.os.Bundle;
importandroid.os.Handler;
importandroid.os.Message;
importandroid.view.View;
importandroid.widget.Button;
importandroid.widget.EditText;
importandroid.widget.TextView;
publicclassSocketDemoextendsActivityimplementsRunnable{
privateTextViewtv_msg=null;
privateEditTexted_msg=null;
privateButtonbtn_send=null;
//privateButtonbtn_login=null;
privatestaticfinalStringHOST="10.0.2.2";
privatestaticfinalintPORT=9999;
privateSocketsocket=null;
privateBufferedReaderin=null;
privatePrintWriterout=null;
privateStringcontent="";
//接收线程发送过来信息,并用TextView显示
publicHandlermHandler=newHandler(){
publicvoidhandleMessage(Messagemsg){
super.handleMessage(msg);
tv_msg.setText(content);
}
};
@Override
publicvoidonCreate(BundlesavedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
tv_msg=(TextView)findViewById(R.id.TextView);
ed_msg=(EditText)findViewById(R.id.EditText01);
btn_send=(Button)findViewById(R.id.Button02);
try{
socket=newSocket(HOST,PORT);
in=newBufferedReader(newInputStreamReader(socket
.getInputStream()));
out=newPrintWriter(newBufferedWriter(newOutputStreamWriter(
socket.getOutputStream())),true);
}catch(IOExceptionex){
ex.printStackTrace();
ShowDialog("loginexception"+ex.getMessage());
}
btn_send.setOnClickListener(newButton.OnClickListener(){
@Override
publicvoidonClick(Viewv){
//TODOAuto-generatedmethodstub
Stringmsg=ed_msg.getText().toString();
if(socket.isConnected()){
if(!socket.isOutputShutdown()){
out.println(msg);
}
}
}
});
//启动线程,接收服务器发送过来的数据
newThread(SocketDemo.this).start();
}
/**
*如果连接出现异常,弹出AlertDialog!
*/
publicvoidShowDialog(Stringmsg){
newAlertDialog.Builder(this).setTitle("notification").setMessage(msg)
.setPositiveButton("ok",newDialogInterface.OnClickListener(){
@Override
publicvoidonClick(DialogInterfacedialog,intwhich){
}
}).show();
}
/**
*读取服务器发来的信息,并通过Handler发给UI线程
*/
publicvoidrun(){
try{
while(true){
if(!socket.isClosed()){
if(socket.isConnected()){
if(!socket.isInputShutdown()){
if((content=in.readLine())!=null){
content+="\n";
mHandler.sendMessage(mHandler.obtainMessage());
}else{
}
}
}
}
}
}catch(Exceptione){
e.printStackTrace();
}
}
}
解析:除了isClose方法,Socket类还有一个isConnected方法来判断Socket对象是否连接成功。 看到这个名字,也许读者会产生误解。 其实isConnected方法所判断的并不是Socket对象的当前连接状态, 而是Socket对象是否曾经连接成功过,如果成功连接过,即使现在isClose返回true,isConnected仍然返回true。因此,要判断当前的Socket对象是否处于连接状态,必须同时使用isClose和isConnected方法,即只有当isClose返回false,isConnected返回true的时候Socket对象才处于连接状态。虽然在大多数的时候可以直接使用Socket类或输入输出流的close方法关闭网络连接,但有时我们只希望关闭OutputStream或InputStream,而在关闭输入输出流的同时,并不关闭网络连接。这就需要用到Socket类的另外两个方法:shutdownInput和shutdownOutput,这两个方法只关闭相应的输入、输出流,而它们并没有同时关闭网络连接的功能。和isClosed、isConnected方法一样,Socket类也提供了两个方法来判断Socket对象的输入、输出流是否被关闭,这两个方法是isInputShutdown()和isOutputShutdown()。shutdownInput和shutdownOutput并不影响Socket对象的状态。
2.基于字节的传输
基于字节传输的时候,只需要把相应的字符串和整数等类型转换为对应的网络字节进行传输即可。具体关于如何把其转换为网络字节,请参《Java整型数与网络字节序byte[]数组转换关系详解》。
更多关于Android相关内容感兴趣的读者可查看本站专题:《Android通信方式总结》、《Android开发入门与进阶教程》、《Android调试技巧与常见问题解决方法汇总》、《Android多媒体操作技巧汇总(音频,视频,录音等)》、《Android基本组件用法总结》、《Android视图View技巧总结》、《Android布局layout技巧总结》及《Android控件用法总结》
希望本文所述对大家Android程序设计有所帮助。