zoukankan      html  css  js  c++  java
  • Android Socket编程基础

    前些天写了一个Android手机在局域网内利用Wifi进行文件传输的Demo,其中用到了Socket编程,故此总结(盗了网友的一些图和文字)。好久好久没来博客园了~~

    1.什么是Socket?

    socket英文意思是插座,只有插上插座,才会有电流。如果把他用在网络中,只有建立了socket连接,才能传输数据。网络中的进程是通过socket来通信的,socket起源于Unix,而Unix/Linux基本哲学之一就是“一切皆文件”,都可以用“打开open –> 读写write/read –> 关闭close”模式来操作。

    我的理解就是Socket就是该模式的一个实现,socket即是一种特殊的文件,一些socket函数就是对其进行的操作(读/写IO、打开、关闭)

     2.使用Socket进行网络通信的过程

      Socket通讯的过程大概可以简述为

                  建立Socket连接-->获得输入/输出流-->读/写数据-->关闭输入/输出流-->关闭Socket

     2.1 Socket 建立连接过程

         我们知道tcp建立连接要进行“三次握手”,即交换三个分组。大致流程如下:

    • 客户端向服务器发送一个SYN J
    • 服务器向客户端响应一个SYN K,并对SYN J进行确认ACK J+1
    • 客户端再想服务器发一个确认ACK K+1


    示意图如下:

    image

    从图中可以看出,当客户端调用connect时,触发了连接请求,向服务器发送了SYN J包,这时connect进入阻塞状态;服务器监听到连接请求,即收到SYN J包,调用accept函数接收请求向客户端发送SYN K ,ACK J+1,这时accept进入阻塞状态;

    客户端收到服务器的SYN K ,ACK J+1之后,这时connect返回,并对SYN K进行确认;服务器收到ACK K+1时,accept返回,至此三次握手完毕,连接建立。

     2.2 获取Socket文件流进行数据通讯

    图例:

    服务端:

    ServerSocket serverSocket = new ServerSocket(PORT);
    Socket client = serverSocket.accept();// accept()方法监听向这个socket的连接并接收连接。它将会阻塞直到连接被建立好。连接建立好后它会返回一个Socket对象。

    InputStream inputstream = client.getInputStream();//获取数据输入流

    byte [] data=new byte[4096];

    inputstream.read(data);//读入数据

    客户端:

    Socket socket = new Socket();

    try {
          socket.bind(null);
          socket.connect((new InetSocketAddress(host, port)), SOCKET_TIMEOUT);//指定ip和端口 建立连接,参数 host为IP地址,port为端口名

          OutputStream stream = socket.getOutputStream(); //获取文件输出流

          stream.write(“socket data”); //向Socket 写入数据

    } catch (IOException e) {
            Log.e(TAG, e.getMessage());
    } finally {
          if (socket != null) {
          if (socket.isConnected()) {
          try {
          socket.close();//关闭socket
          } catch (IOException e) {
          e.printStackTrace();

        }
    }

    3.使用线程实现服务器端与客户端的双向通信

    在应用中,数据通讯肯定是有来有回的,那么我们就要结合多线程技术使用Socket 

    设计思想是,用两个线程,一个线程专门用于处理服务器端的读,另一个线程专门用于处理服务器端的写。客户端同理。

    代码如下,程序共有六个类。

     

    服务器端和其输入输出线程:

    package com.example.network;

    import java.net.ServerSocket;
    import java.net.Socket;

    public class MainServer
    {
    public static void main(String[] args) throws Exception
    {
    ServerSocket serverSocket = new ServerSocket(4000);

    while (true)
    {
    // 一直处于监听状态,这样可以处理多个用户
    Socket socket = serverSocket.accept();

    // 启动读写线程
    new ServerInputThread(socket).start();
    new ServerOutputThread(socket).start();

    }

    }

    }

    package com.example.network;

    import java.io.IOException;
    import java.io.InputStream;
    import java.net.Socket;

    public class ServerInputThread extends Thread
    {
    private Socket socket;

    public ServerInputThread(Socket socket)
    {
    super();
    this.socket = socket;
    }

    @Override
    public void run()
    {
    try
    {
    // 获得输入流
    InputStream is = socket.getInputStream();

    while (true)
    {
    byte[] buffer = new byte[1024];

    int length = is.read(buffer);

    String str = new String(buffer, 0, length);

    System.out.println(str);

    }

    }
    catch (IOException e)
    {
    e.printStackTrace();
    }
    }

    }

    package com.example.network;

    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.io.OutputStream;
    import java.net.Socket;

    public class ServerOutputThread extends Thread
    {
    private Socket socket;

    public ServerOutputThread(Socket socket)
    {
    super();
    this.socket = socket;
    }

    @Override
    public void run()
    {
    try
    {

    OutputStream os = socket.getOutputStream();

    while (true)
    {
    BufferedReader reader = new BufferedReader(
    new InputStreamReader(System.in));

    String line = reader.readLine();

    os.write(line.getBytes());
    }
    }
    catch (IOException e)
    {
    e.printStackTrace();
    }

    }

    }

     

    客户端和其输入输出线程(其输入输出线程和服务器端的完全一样):  

    package com.example.network;

    import java.net.Socket;

    public class MainClient
    {

    public static void main(String[] args) throws Exception
    {
    Socket socket = new Socket("127.0.0.1", 4000);

    new ClientInputThread(socket).start();
    new ClientOutputThread(socket).start();

    }
    }

    package com.example.network;

    import java.io.IOException;
    import java.io.InputStream;
    import java.net.Socket;

    public class ClientInputThread extends Thread
    {
    private Socket socket;

    public ClientInputThread(Socket socket)
    {
    super();
    this.socket = socket;
    }

    @Override
    public void run()
    {
    try
    {
    // 获得输入流
    InputStream is = socket.getInputStream();

    while (true)
    {
    byte[] buffer = new byte[1024];

    int length = is.read(buffer);

    String str = new String(buffer, 0, length);

    System.out.println(str);

    }

    }
    catch (IOException e)
    {
    e.printStackTrace();
    }
    }

    }


    package com.example.network;

    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.io.OutputStream;
    import java.net.Socket;

    public class ClientOutputThread extends Thread
    {
    private Socket socket;

    public ClientOutputThread(Socket socket)
    {
    super();
    this.socket = socket;
    }

    @Override
    public void run()
    {
    try
    {

    OutputStream os = socket.getOutputStream();

    while (true)
    {
    BufferedReader reader = new BufferedReader(
    new InputStreamReader(System.in));

    String line = reader.readLine();

    os.write(line.getBytes());
    }
    }
    catch (IOException e)
    {
    e.printStackTrace();
    }

    }

    }



     

  • 相关阅读:
    TreeList Linq
    MasterDetail Linq
    C# 事务处理
    设计模式——代理模式(Proxy Pattern)
    设计模式——装饰模式(Decorator Pattern)
    C# 调用WCF服务
    加密解密
    Effective C#高效编程(02:常量)
    切换城市功能
    DataPager控件使用
  • 原文地址:https://www.cnblogs.com/ikarl/p/4505505.html
Copyright © 2011-2022 走看看