TCP与UDP的区别

TCP 和UDP都是传输层的协议, 但TCP是面向连接、可靠的字节流服务,传输速度慢,而UDP是用户数据报协议,是一种面向数据报的协议,不需要建立连接,传输速度快。
对于TCP要经过3次握手:
第一次握手:请求端发送一条消息到服务端,服务端收到消息。ack
第二次握手:接收端接收到消息后发送一条消息给请求端,表示服务端已经收到了消息 ack <–>syn+1
第三次握手:请求端接收到服务端返回的消息,证明建立了连接,才开始传输数据 ack <—>ack+1

何为连接:双方记录双方的信息(ip和port)
连接与线程无关,所以不应把连接放在线程了执行,否则线程挂掉会导致连接挂掉。

UDP编程

接收方创建步骤:
  1. 创建一个DatagramSocket对象,并指定监听的端口号
    DatagramSocket socket = new DatagramSocket (4567);
  2. 创建一个byte数组用于接收
    byte data[] = new byte[1024];
  3. 创建一个空的DatagramPackage对象
    DatagramPackage package = new DatagramPackage(data , data.length);
  4. 使用receive方法接收发送方所发送的数据,同时这也是一个阻塞的方法
    socket.receive(package);
  5. 得到发送过来的数据
    new String(package.getData() , package.getOffset() , package.getLength());
发送方创建步骤:
  1. 创建一个DatagramSocket对象
    DatagramSocket socket = new DatagramSocket (4567);
  2. 创建一个 InetAddress , 相当于是地址
    InetAddress serverAddress = InetAddress.getByName(“想要发送到的那个IP地址”);
  3. 这是随意发送一个数据
    String str = “ok”;
  4. 转为byte类型
    byte data[] = str.getBytes();
  5. 创建一个DatagramPacket 对象,并指定要讲这个数据包发送到网络当中的哪个地址,以及端口号
    DatagramPacket package = new DatagramPacket (data , data.length , serverAddress , 4567);
  6. 调用DatagramSocket对象的send方法 发送数据
    socket . send(package);

UDPClient代码

package com.ldc.materialdesign.udp;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;

/**
 * Created by AA on 2017/1/4.
 */

public class UDPClient {

    private static final int SERVER_PORT = 6000;//端口
    private DatagramSocket dSocket = null;
    private ISocketResponse mISocketResponse = null;

    public UDPClient(ISocketResponse mISocketResponse) {
        super();
        this.mISocketResponse = mISocketResponse;
    }

    public String send(String ip, int port, String msg) {
        StringBuilder sb = new StringBuilder();
        InetAddress local = null;
        try {
            local = InetAddress.getByName(ip); // 本机测试
            sb.append("已找到服务器,连接中...").append("\n");
        } catch (UnknownHostException e) {
            sb.append("未找到服务器.").append("\n");
            e.printStackTrace();
        }
        try {
            dSocket = new DatagramSocket(); // 注意此处要先在配置文件里设置权限,否则会抛权限不足的异常
            sb.append("正在连接服务器...").append("\n");
        } catch (SocketException e) {
            e.printStackTrace();
            sb.append("服务器连接失败.").append("\n");
        }
        int msg_len = msg == null ? 0 : msg.length();
        DatagramPacket dPacket = new DatagramPacket(msg.getBytes(), msg_len,
                local, port);
        try {
            dSocket.send(dPacket);
            sb.append("消息发送成功!").append("\n");
            dSocket.receive(dPacket);
            mISocketResponse.onSocketResponse(dPacket.getData());
        } catch (IOException e) {
            e.printStackTrace();
            sb.append("消息发送失败.").append("\n");
        }
        dSocket.close();
        return sb.toString();
    }
}

UDPServer代码

package com.ldc.materialdesign.udp;

import android.util.Log;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;

/**
 * Created by AA on 2017/1/4.
 */

public class UDPServer implements Runnable{
    private static final int PORT = 6000;
    private byte[] msg = new byte[1024];
    private boolean life = true;
    public UDPServer() {
    }

    public boolean isLife() {
        return life;
    }

    public void setLife(boolean life) {
        this.life = life;
    }

    @Override
    public void run() {
        DatagramSocket dSocket = null;
        DatagramPacket dPacket = new DatagramPacket(msg, msg.length);
        try {
            dSocket = new DatagramSocket(PORT);
            while (life) {
                try {
                    dSocket.receive(dPacket);
                    Log.i("UDPServer", new String(dPacket.getData()));
                    dPacket.setData("ok".getBytes());
                    dSocket.send(dPacket);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        } catch (SocketException e) {
            e.printStackTrace();
        }
    }
}

调用先开启Server再发送数据报

// 开启服务器
        ExecutorService exec = Executors.newCachedThreadPool();
        UDPServer server = new UDPServer();
        exec.execute(server);
        // 发送消息
        send_bt.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        UDPClient client = new UDPClient(new ISocketResponse() {
                            @Override
                            public void onSocketResponse(byte[] responseData) {
                                Log.e("onSocketResponse", new String(responseData));
                            }
                        });
                        Log.e("client",client.send("localhost",6000,msg_et.getText().toString()));
                    }
                }).start();
            }
        });

TCP编程

TCP的客户端

例如:tcp抄读电表数据的例子
1. 打开客户端、连接服务端

tcpnioClient = new TCPNIOClient(this.getApplicationContext(), socketListener, "59.39.7.155", 9600);
tcpnioClient.open();
  1. 登录通信服务器
String temp = ProtocolCommunicationServer.frame_login(terminalAddr);
                    socketData.packetData(StringUtils.HexStringToByteArray(temp));
                    tcpnioClient.sendData(socketData);
  1. 连接终端
String temp = ProtocolCommunicationServer.frame_queryIfCanEstablishConnection(terminalAddr);
sendData(temp);
  1. 抄读数据
if (datas.size()>0){
      sendData(datas.get(0));
      datas.remove(0);
   }
  1. 断开连接终端
String disconnectStr = ProtocolCommunicationServer.frame_disconnectServer(terminalAddr);
                                sendData(disconnectStr);
  1. 登出通信服务器
String logout = ProtocolCommunicationServer.frame_logout(terminalAddr);
                            sendData(logout);
TCP的服务端(没写)