Socket在Android中的用法
来源:互联网 发布:魏强斌 知乎 编辑:程序博客网 时间:2024/06/06 06:35
Socket的简介
网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket。
在Android中我们常用的Socket形式为一方是客户端一方是服务端,分别具有数据的发送与接受的功能
在客户端使用Soket时,首先应了解服务端的Ip地址(只有知道,才能找到服务器)并知道服务器所监听
的端口号,才能顺利的建立连接在服务端使用Socket时,应首先规定出需要监听的端口号,以便准确监听。
客户端Soket的简单用法
public class MsgClient { public DataOutputStream outs; public static void main(String[] args) { try { MsgClient client = new MsgClient(); client.connServer("127.0.0.1", 9090); } catch (UnknownHostException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } public void sendTextMsg(DataOutputStream out, String msg) throws IOException { byte[] bytes = msg.getBytes(); out.write(bytes); out.flush(); } public void connServer(String ip, int port) throws UnknownHostException, IOException { Socket client = new Socket(ip, port); InputStream in = client.getInputStream(); OutputStream out = client.getOutputStream(); outs = new DataOutputStream(out); sendTextMsg(outs, "我发送啦"); } }
Socket客户端的用法比较简单,如上述一样,指定客户端Ip和监听端口,然后在连接成功后,就能够通过获取相应的流来进行数据的发送与接收操作
Socket服务端
public static void main(String[] args) { try { MsgServer server = new MsgServer(); server.setUpServer(9090); } catch (IOException e) { e.printStackTrace(); } } public void setUpServer(int port) throws IOException { ServerSocket server = new ServerSocket(port); while(true) { Socket client = server.accept();//阻塞状态,生成 System.out.println("客户端IP:"+client.getRemoteSocketAddress()); processMesage(client); } } private void processMesage(Socket client) throws IOException { InputStream ins = client.getInputStream(); DataInputStream dins = new DataInputStream(ins); //服务端接收数据 while(true) { String msg = dins.readLine(); System.out.println("发来的内容是:"+msg); } }
服务器的原理也和客户端相似,通过指定对应的Port来监听客户端的连接,当 server.accept(); 的时候处于阻塞状态等待客户端的连接,当客户端连接时生成Socket实例,针对新的socket对象可进行相关操作
Socket心跳包
在使用过程中,由于客户端和服务端的机制原因,客户端和服务器端无法准确的了解对方是否还存在,所以心跳包也就此出现,基本原理就是客户端定时向服务端报告自己在线,服务端进行接收信息了解客户端在线,并会送客户端信息,具体代码如下
public class Server { /** * 要处理客户端发来的对象,并返回一个对象,可实现该接口。 */ public interface ObjectAction{ Object doAction(Object rev); } public static final class DefaultObjectAction implements ObjectAction{ public Object doAction(Object rev) { System.out.println("处理并返回:"+rev); return rev; } } public static void main(String[] args) { int port = 65432; Server server = new Server(port); server.start(); } private int port; private volatile boolean running=false; private long receiveTimeDelay=3000; private ConcurrentHashMap<Class, ObjectAction> actionMapping = new ConcurrentHashMap<Class,ObjectAction>(); private Thread connWatchDog; public Server(int port) { this.port = port; } public void start(){ if(running)return; running=true; connWatchDog = new Thread(new ConnWatchDog()); connWatchDog.start(); } @SuppressWarnings("deprecation") public void stop(){ if(running)running=false; if(connWatchDog!=null)connWatchDog.stop(); } public void addActionMap(Class<Object> cls,ObjectAction action){ actionMapping.put(cls, action); } class ConnWatchDog implements Runnable{ public void run(){ try { ServerSocket ss = new ServerSocket(port,5); while(running){ Socket s = ss.accept(); new Thread(new SocketAction(s)).start(); } } catch (IOException e) { e.printStackTrace(); Server.this.stop(); } } } class SocketAction implements Runnable{ Socket s; boolean run=true; //逻辑问题,上次接收时间默认应为0 long lastReceiveTime = System.currentTimeMillis();// long lastReceiveTime = 0; public SocketAction(Socket s) { this.s = s; } public void run() { while(running && run){ if(System.currentTimeMillis()-lastReceiveTime>receiveTimeDelay){ System.out.println("我进来了"); overThis(); }else{ try { InputStream in = s.getInputStream(); if(in.available()>0){ ObjectInputStream ois = new ObjectInputStream(in); Object obj = ois.readObject(); lastReceiveTime = System.currentTimeMillis(); System.out.println("接收:\t"+obj); ObjectAction oa = actionMapping.get(obj.getClass()); oa = oa==null?new DefaultObjectAction():oa; Object out = oa.doAction(obj); if(out!=null){ ObjectOutputStream oos = new ObjectOutputStream(s.getOutputStream()); oos.writeObject(out); oos.flush(); } }else{ Thread.sleep(10); } } catch (Exception e) { e.printStackTrace(); overThis(); } } } } private void overThis() { if(run)run=false; if(s!=null){ try { s.close(); } catch (IOException e) { e.printStackTrace(); } } System.out.println("关闭:"+s.getRemoteSocketAddress()); System.out.println("断开连接"); } }}
public class Client { /** * 处理服务端发回的对象,可实现该接口。 */ public static interface ObjectAction{ void doAction(Object obj,Client client); } public static final class DefaultObjectAction implements ObjectAction{ public void doAction(Object obj,Client client) { System.out.println("处理:\t"+obj.toString()); } } public static void main(String[] args) throws UnknownHostException, IOException { String serverIp = "127.0.0.1"; int port = 65432; Client client = new Client(serverIp,port); client.start(); } private String serverIp; private int port; private Socket socket; private boolean running=false; private long lastSendTime; private ConcurrentHashMap<Class, ObjectAction> actionMapping = new ConcurrentHashMap<Class,ObjectAction>(); public Client(String serverIp, int port) { this.serverIp=serverIp;this.port=port; } public void start(){ if(running)return; try { socket = new Socket(serverIp,port); System.out.println("本地端口:"+socket.getLocalPort()); lastSendTime=System.currentTimeMillis(); running=true; new Thread(new KeepAliveWatchDog()).start(); new Thread(new ReceiveWatchDog()).start(); } catch (IOException e) { System.out.println("u发发"); try { Thread.sleep(10000); } catch (InterruptedException e1) { e1.printStackTrace(); } System.out.println(port+""); Client client = new Client(serverIp,port); client.start(); e.printStackTrace(); } } public void stop(){ if(running)running=false; System.out.println("Client stop"); } /** * 添加接收对象的处理对象。 * @param cls 待处理的对象,其所属的类。 * @param action 处理过程对象。 */ public void addActionMap(Class<Object> cls,ObjectAction action){ actionMapping.put(cls, action); } public void sendObject(Object obj) { try { ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream()); oos.writeObject(obj); System.out.println("发送:\t"+obj); oos.flush(); } catch (IOException e) { System.out.println("尼玛炸了"); stop(); start(); e.printStackTrace(); } } class SendMessage implements Runnable { @Override public void run() { while (true) { Scanner scanner = new Scanner(System.in); String s = scanner.nextLine(); } } } class KeepAliveWatchDog implements Runnable{ long checkDelay = 10; long keepAliveDelay = 2000; public void run() { while(running){ if(System.currentTimeMillis()-lastSendTime>keepAliveDelay){ Client.this.sendObject(new KeepAlive()); lastSendTime = System.currentTimeMillis(); }else{ try { Thread.sleep(checkDelay); } catch (InterruptedException e) { e.printStackTrace(); Client.this.stop(); } } } } } class ReceiveWatchDog implements Runnable{ public void run() { while(running){ try { InputStream in = socket.getInputStream(); if(in.available()>0){ ObjectInputStream ois = new ObjectInputStream(in); Object obj = ois.readObject(); System.out.println("接收:\t"+obj); ObjectAction oa = actionMapping.get(obj.getClass()); oa = oa==null?new DefaultObjectAction():oa; oa.doAction(obj, Client.this); }else{ Thread.sleep(10); } } catch (Exception e) { e.printStackTrace(); Client.this.stop(); } } } }}
public class KeepAlive implements Serializable { private static final long serialVersionUID = -2813120366138988480L; /* 覆盖该方法,仅用于测试使用。 * @see java.lang.Object#toString() */ @Override public String toString() { return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())+"\t维持连接包"; }}
Socket中传输文件(并能传递文件名)
/** * Created by admin on 2016/9/20/0020. * * 客户端给服务端发送文件夹 */public class TCPServer { static int size=10*1024; static byte[] buf=new byte[size]; static int len=-1; public static void main(String[] args) throws Exception{ ServerSocket ss=null; OutputStream out=null; Socket s=null; try { ss=new ServerSocket(9987); System.out.println("等待客户端连接"); s=ss.accept(); System.out.println("连接成功");// InputStream in=s.getInputStream(); out=s.getOutputStream(); long start=System.currentTimeMillis(); System.out.println("开始发送文件"); String fileName="D:\\新建文件夹\\demo1";//"I:"+File.separator; if(!fileName.endsWith(File.separator)){ fileName+=File.separator; } File file=new File(fileName); String parent=file.getParent(); if(parent==null){ File[] fs=file.listFiles(); for(int i=0;i<fs.length;i++){ if(fs[i].isHidden()) { System.out.println("隐藏文件"+fs[i].getAbsolutePath()+",不会被发送"); continue; } test(fs[i],out,fs[i].getParent()); } }else{ test(file,out,parent); } System.out.println("文件发送成功"+(System.currentTimeMillis()-start)+"ms"); out.write("接受成功".getBytes()); out.flush(); } finally { if(out!=null)out.close(); if(s!=null)s.close(); if(ss!=null)ss.close(); } } private static void test(File file,OutputStream out,String sendFileName)throws Exception{ FileInputStream in=null; String fname=file.getAbsolutePath(); String name=fname.replace(sendFileName, ""); if(file.isDirectory()){ File[] fs=file.listFiles(); out.write(new byte[]{(byte)2}, 0, 1);//2:文件夹名 int fileLength=name.getBytes().length; out.write(intToBytes(fileLength),0,4);//文件名的长度 out.write(name.getBytes(),0,name.getBytes().length);//文件名 System.out.println("文件夹:"+name+" "+name.length()); out.flush(); for(int i=0;i<fs.length;i++){ if(fs[i].isHidden()) { System.out.println("隐藏文件"+fs[i].getAbsolutePath()+",不会被发送"); continue; } test(fs[i],out,sendFileName); } }else{ out.write(new byte[]{(byte)1}, 0, 1);//1:文件名 int fileLength=name.getBytes().length; out.write(intToBytes(fileLength),0,4);//文件夹名的长度 out.write(name.getBytes(),0,name.getBytes().length);//文件夹名 System.out.println("文件:"+name+" "+name.length()+" "+file.length()); out.flush(); in=new FileInputStream(file); out.write(new byte[]{(byte)0}, 0, 1);//0表示文件数据 out.write(longToBytes(file.length()),0,8);//文件的长度 out.flush(); while((len=in.read(buf,0,size))!=-1){ out.write(buf,0,len); out.flush(); } in.close(); } } private static byte[] intToBytes(int i){ byte[] b=new byte[4]; b[0]=(byte)((i>>>24)&255); b[1]=(byte)((i>>>16)&255); b[2]=(byte)((i>>>8)&255); b[3]=(byte)(i&255); return b; } private static byte[] longToBytes(long i){ byte[] b=new byte[8]; b[0]=(byte)((i>>>56)&255); b[1]=(byte)((i>>>48)&255); b[2]=(byte)((i>>>40)&255); b[3]=(byte)((i>>>32)&255); b[4]=(byte)((i>>>24)&255); b[5]=(byte)((i>>>16)&255); b[6]=(byte)((i>>>8)&255); b[7]=(byte)(i&255); return b; }}
public class TCPClient { public static void main(String[] args) throws Exception{ System.setOut(new PrintStream(new FileOutputStream("D:\\log.txt"))); Socket s=null; InputStream in=null; try { s=new Socket("127.0.0.1", 9987); String savePath="D:\\新建文件夹\\demo2";//"D:"+File.separator+"test"+File.separator; in=s.getInputStream(); int size=10*1024; byte[] buf=new byte[size]; int len=-1; byte[] bs=new byte[size]; while((len=in.read(buf, 0, size))!=-1){ writeData(buf,0,len,savePath,bs); } if(out!=null){ out.flush(); out.close(); } } finally { if(in!=null) in.close(); if(s!=null) s.close(); } } static FileOutputStream out=null; static long count=0;//计算是否完成数据的读取,开始下一条命令 static int cmd=-1; static int bsl=0; private static void writeData(byte[] buf,int off, int len,String savePath,byte[] bs) throws Exception{ if(len-off==0)return; System.out.println("偏移量:"+off+"命令"+cmd+"数量:"+count); int i=off; if(count==0l){//如果一条命令的数据已经读完就开始读取下一条命令 cmd=buf[i++]; System.out.println("获取命令:"+cmd); count=-1l; if(len-i==0)return; writeData(buf,i,len,savePath,bs); }else if(count==-1l){//读取文件(夹)名称的长度或文件的大小 System.out.println("获取长度"); switch (cmd){ case 0: if(len-i+bsl<8){ System.arraycopy(buf, i, bs, bsl, len-i); System.out.println("读取长度1:"+(len-i)+" 未读取完"); bsl=len-i; i=0; return; } System.arraycopy(buf, i, bs, bsl, 8-bsl); System.out.println("读取长度1:"+(8-bsl)+" 读取完"); count=bytesToLong(bs, 0); i+=8-bsl; bsl=0; writeData(buf,i,len,savePath,bs); break; case 1: case 2: if(len-i+bsl<4){ System.arraycopy(buf, i, bs, bsl, len-i); System.out.println("读取长度2:"+(len-i)+" 未读取完"); bsl=len-i; i=0; return; } System.arraycopy(buf, i, bs, bsl, 4-bsl); System.out.println("读取长度2:"+(4-bsl)+" 读取完"); count=bytesToInt(bs, 0); i+=4-bsl; bsl=0; writeData(buf,i,len,savePath,bs); break; } }else{//写入文件或创建文件夹、创建文件输出流 System.out.println("3"); switch (cmd){ case 0: System.out.println("写入文件"); if(len-i-count>0){ try{ System.out.println("写入文件 长度:"+count+"文件写入完成"); out.write(buf, i, (int)count); i+=count; count=0; out.flush(); }finally{ if(out!=null)out.close(); } writeData(buf,i,len,savePath,bs); }else{ System.out.println("写入文件 长度:"+(len-i)+"文件写入没有完成"); out.write(buf,i,len-i); count-=len-i; i=0; }break; case 1: if(len-i-count<0){ System.out.println("获取文件名字:"+(len-i)+"写入没有完成 剩余长度"+count); System.arraycopy(buf, i, bs, bsl, len-i); bsl+=len-i; count-=bsl; i=0; return; }else{ System.out.println("获取文件名字:"+(count-bsl)+"写入完成 剩余长度"); System.arraycopy(buf, i, bs, bsl, (int)count); String name=new String(bs,0,(int)count+bsl); System.out.println("文件:"+savePath+name); out=new FileOutputStream(savePath+name); bsl=0; i+=count; count=0; writeData(buf,i,len,savePath,bs); } break; case 2: if(len-i-count<0){ System.out.println("获取文件夹名字:"+(len-i)+"写入没有完成 剩余长度"+count); System.arraycopy(buf, i, bs, bsl, len-i); bsl+=len-i; count-=bsl; i=0; return; }else{ System.out.println(len+" "+count+" "+bsl+" "); System.out.println("获取文件夹名字:"+(count-bsl)+"写入完成 剩余长度"); System.arraycopy(buf, i, bs, bsl, (int)count); String name=new String(bs,0,bsl+(int)count); File file=new File(savePath+name); bsl=0; i+=count; count=0; if(!file.exists()){ file.mkdirs(); } System.out.println("文件夹:"+savePath+name); writeData(buf,i,len,savePath,bs); } break; } } } private static int bytesToInt(byte[] buf,int off){ int i=0; i=i|((buf[off]&255)<<24); i=i|((buf[off+1]&255)<<16); i=i|((buf[off+2]&255)<<8); i=i|(buf[off+3]&255); return i; } private static long bytesToLong(byte[] buf,int off){ long i=0; i=i|(((long)buf[off]&255)<<56) |(((long)buf[off+1]&255)<<48) |(((long)buf[off+2]&255)<<40) |(((long)buf[off+3]&255)<<32) |(((long)buf[off+4]&255)<<24) |(((long)buf[off+5]&255)<<16) |(((long)buf[off+6]&255)<<8) |((long)buf[off+7]&255); return i; }}
具体实现原理我也没看懂···(好尴尬),再次作为记录,如果小伙伴们知道,欢迎帮本宝宝指个明路。
0 0
- Socket在Android中的用法
- Socket在Android中的应用
- Socket在Android中的应用
- onActivityResult在android中的用法
- onActivityResult在android中的用法
- onActivityResult在android中的用法
- onActivityResult在android中的用法
- onActivityResult在android中的用法
- Grpc在Android中的用法
- Android在Socket通信中的辅助类
- Socket在Android开发中的应用
- ioctl在socket中的一些用法及示例
- ioctl在socket中的一些用法及示例
- ioctl&fcntl 在socket中的一些用法及示例
- ioctl在socket中的一些用法和示例
- ioctl在socket中的一些用法及示例
- ioctl在socket中的一些用法及示例
- ioctl在socket中的一些用法及示例
- springMVC 格式化
- 汉诺塔问题--递归实现
- android padding margin和html padding margin的区别
- 14、Fragment
- springMVC 数据验证
- Socket在Android中的用法
- bzoj 3833 [Poi2014]Solar lamps 树套树 splay
- openfire 拦截servlet请求代码解析
- org.apache.catalina.util.DefaultAnnotationProcessor cannot be cast to org.ap解决方
- contOS7(Linux)安装maven
- Linux下Tomcat 在控制台输出日志信息
- linux下解决mysql区分大小写问题
- SDRAM中数据掩码DQM的作用
- openfire 后台用户登录认证代码解析