zoukankan      html  css  js  c++  java
  • UDP通信简单 小结

    Android手机版和电脑版 效果图: 通过WiFi局域网 电脑和手机连接通信. 电脑版本和手机版本使用了相同的消息发送头协议, 可以相互接收消息. 若有做的不好的地方还希望大家指导一下.

    1. 手机版

    添加权限 AndroidManifest.xml

        <uses-permission android:name="android.permission.INTERNET" />
        <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    View Code

    页面 activity_main.xml

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >
    
        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true"
            android:layout_alignParentLeft="true"
            android:layout_alignParentRight="true"
            android:layout_alignParentTop="true"
            android:orientation="vertical" >
    
            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content" >
    
                <EditText
                    android:id="@+id/editText1"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_weight="1"
                    android:ems="10" >
    
                    <requestFocus />
                </EditText>
    
                <Button
                    android:id="@+id/button1"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_weight="1"
                    android:text="连接" />
            </LinearLayout>
    
            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content" >
    
                <EditText
                    android:id="@+id/editText2"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_weight="1"
                    android:ems="10" />
    
                <Button
                    android:id="@+id/button2"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_weight="1"
                    android:text="发送" />
            </LinearLayout>
    
            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content" >
    
                <TextView
                    android:id="@+id/textView1"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="Large Text"
                    android:textAppearance="?android:attr/textAppearanceLarge" />
            </LinearLayout>
    
            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:orientation="vertical" >
    
                <ScrollView
                    android:layout_width="fill_parent"
                    android:layout_height="wrap_content"
                    android:fadingEdge="vertical"
                    android:scrollbars="vertical" >
    
                    <TextView
                        android:id="@+id/textView2"
                        android:layout_width="match_parent"
                        android:layout_height="match_parent"
                        android:text="Large Text"/>
                </ScrollView>
            </LinearLayout>
        </LinearLayout>
    
    </RelativeLayout>
    View Code

    后台代码 MainActivity.java

    package com.example.udppacket;
    
    import android.os.Bundle;
    import android.os.Handler;
    import android.os.Message;
    import android.support.v7.app.ActionBarActivity;
    import android.view.View;
    import android.view.Window;
    import android.widget.EditText;
    import android.widget.TextView;
    import android.widget.Toast;
    
    import com.java.net.IPUtils;
    import com.java.net.MessageEntity;
    import com.java.net.UdpEntitiy;
    import com.java.net.UdpEntitiy.ReceivesListener;
    
    public class MainActivity extends ActionBarActivity {
    
        EditText ip;
        EditText send;
        TextView txt;
        TextView msgs;
    
        UdpEntitiy udp;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
    
            this.requestWindowFeature(Window.FEATURE_NO_TITLE);
    
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            ip = (EditText) findViewById(R.id.editText1);
            send = (EditText) findViewById(R.id.editText2);
            txt = (TextView) findViewById(R.id.textView1);
            msgs = (TextView) findViewById(R.id.textView2);
    
            send.setText("Hello Word!");
            txt.setText("");
            msgs.setText("");
            ip.setText(IPUtils.getHostIP());
    
            udp = UdpEntitiy.getUdpEntitiy();
    
            /**
             * 监听消息
             * */
            udp.onReceiveMessage(new ReceivesListener() {
    
                @Override
                public void onReceiveMessage(MessageEntity messageEntity) {
                    // TODO Auto-generated method stub
    
                    Message msg = new Message();
                    msg.obj = messageEntity;
                    msgHd.sendMessage(msg);
                }
            });
            // 连接
            findViewById(R.id.button1).setOnClickListener(
                    new View.OnClickListener() {
    
                        @Override
                        public void onClick(View v) {
                            // TODO Auto-generated method stub
                            if (!udp.isReceive()) {
                                udp.startReceive();
                                Toast.makeText(MainActivity.this, "已连接!", Toast.LENGTH_SHORT).show();
                            }else {
                                udp.stopReceive();
                                Toast.makeText(MainActivity.this, "已关闭!", Toast.LENGTH_SHORT).show();
                            }
                        }
                    });
            // 发送
            findViewById(R.id.button2).setOnClickListener(
                    new View.OnClickListener() {
    
                        @Override
                        public void onClick(View v) {
                            // TODO Auto-generated method stub
                            if (!send.getText().toString().equals("")) {
                                udp.send(ip.getText().toString(), send.getText().toString());
                                msgs.append("我 : " + send.getText().toString() + "
    ");
                                send.setText("");
                            }else {
                                Toast.makeText(MainActivity.this, "请输入消息!", Toast.LENGTH_SHORT).show();
                            }
                        }
                    });
        }
    
        Handler msgHd = new Handler() {
    
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                MessageEntity me = (MessageEntity) msg.obj;
                if (me.type.equals("00")) {// 文字
                    msgs.append("来自 [ " + me.sendIP + " ] :" + me.getString() + "
    ");
    
                }
            };
        };
    
    }
    View Code

    以下是类库代码:

    获取IP地址 IPUtils.java 可要可不要

    package com.java.net;
    
    import java.net.Inet6Address;
    import java.net.InetAddress;
    import java.net.NetworkInterface;
    import java.net.SocketException;
    import java.util.Enumeration;
    
    import android.content.Context;
    import android.net.wifi.WifiInfo;
    import android.net.wifi.WifiManager;
    
    public class IPUtils {
    
        /***
         * 
         * <uses-permission android:name="android.permission.INTERNET"/>
            <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
         * /
        /**
         * 获取ip地址
         * @return
         */
        public static String getHostIP() {
    
            String hostIp = null;
            try {
                Enumeration nis = NetworkInterface.getNetworkInterfaces();
                InetAddress ia = null;
                while (nis.hasMoreElements()) {
                    NetworkInterface ni = (NetworkInterface) nis.nextElement();
                    Enumeration<InetAddress> ias = ni.getInetAddresses();
                    while (ias.hasMoreElements()) {
                        ia = ias.nextElement();
                        if (ia instanceof Inet6Address) {
                            continue;// skip ipv6
                        }
                        String ip = ia.getHostAddress();
                        if (!"127.0.0.1".equals(ip)) {
                            hostIp = ia.getHostAddress();
                            break;
                        }
                    }
                }
            } catch (SocketException e) {
                e.printStackTrace();
            }
            return hostIp;
    
        }
    
    
        /*
         **
         * 获取本机IPv4地址
         *
         * @param context
         * @return 本机IPv4地址;null:无网络连接
         */
        public static String getIpAddress(Context context) {
            // 获取WiFi服务
            WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
            // 判断WiFi是否开启
            if (wifiManager.isWifiEnabled()) {
                // 已经开启了WiFi
                WifiInfo wifiInfo = wifiManager.getConnectionInfo();
                int ipAddress = wifiInfo.getIpAddress();
                String ip = intToIp(ipAddress);
                return ip;
            } else {
                // 未开启WiFi
                return getIpAddress();
            }
        }
    
        private static String intToIp(int ipAddress) {
            return (ipAddress & 0xFF) + "." +
                    ((ipAddress >> 8) & 0xFF) + "." +
                    ((ipAddress >> 16) & 0xFF) + "." +
                    (ipAddress >> 24 & 0xFF);
        }
    
        /**
         * 获取本机IPv4地址
         *
         * @return 本机IPv4地址;null:无网络连接
         */
        private static String getIpAddress() {
            try {
                NetworkInterface networkInterface;
                InetAddress inetAddress;
                for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements(); ) {
                    networkInterface = en.nextElement();
                    for (Enumeration<InetAddress> enumIpAddr = networkInterface.getInetAddresses(); enumIpAddr.hasMoreElements(); ) {
                        inetAddress = enumIpAddr.nextElement();
                        if (!inetAddress.isLoopbackAddress() && !inetAddress.isLinkLocalAddress()) {
                            return inetAddress.getHostAddress();
                        }
                    }
                }
                return null;
            } catch (SocketException ex) {
                ex.printStackTrace();
                return null;
            }
        }
    
    }
    View Code

    发送接收消息包装类库 :MessageEntity.java

    package com.java.net;
    
    import java.io.ByteArrayOutputStream;
    import java.io.File;
    
    import android.graphics.Bitmap;
    import android.graphics.BitmapFactory;
    
    /**
     * 标识 000000, 6位 类型00... , 00 :字符串, 01 :图片, 02 :文件 ... 2位(不足使用字母代替) 是否接收确认0 - 1
     * , 0 :不确认 ,1 :确认 1位 默认不确认0 是否为最后一个 0 - 1, 0 :不是最后一个, 1 :最后一个 1位 默认最后一个1
     * 数据byte[]
     * */
    public class MessageEntity {
        // 初始化
        private void init() {
            flagNo = getRandom();// 6 位随机数
            type = "00";
            isPass = "0";
            isLast = "1";
        }
    
        public MessageEntity() {
            init();
        }
        public MessageEntity(String s){
            init();
            type = "00";//字符串
            datas = s.getBytes();
        }
        public MessageEntity(File s){
            init();
            type = "02";//文件
            //文件流转换
        }
        public MessageEntity(Bitmap s){
            init();
            type = "01";//Bitmap  图片
            datas = Bitmap2Bytes(s);
        }
        //根据字节获取图片
        public Bitmap getBitmap(){
            if (datas != null && datas.length > 0) {
                return Bytes2Bimap(datas);
            }
            return null;
        }
        //根据字节获取字符串
        public String getString(){
            if (datas != null && datas.length > 0) {
                return new String(datas, 0, datas.length);
            }
            return null;
        }
        //根据字节获取文件
        public String getFile(){
            if (datas != null && datas.length > 0) {
                //代码
                return null;
            }
            return null;
        }
        //获取头字节
        public byte[] getHeadToByte(){
            return (getFlagNo() + "," + type + "," + isPass + "," + isLast).getBytes();
        }
        //根据字节 重置头部参数
        public MessageEntity resetParameter(byte[] b, MessageEntity m){
            if (m == null) {
                m = new MessageEntity();
            }
            if (b != null && b.length > 0) {
                String s = new String(b, 0, b.length);
                resetParameter(s,m);
            }
            return m;
        }
        //根据字节 重置头部参数
        public MessageEntity resetParameter(String b, MessageEntity m){
            String[] ss = b.split(",");
            if (ss.length >= 4) {
                m.flagNo = ss[0];
                m.type = ss[1];
                m.isPass = ss[2];
                m.isLast = ss[3];
            }
            return m;
        }
        private String flagNo;// 消息编号
        public String getFlagNo(){
            return flagNo;
        }
        public String type;// 消息类型
        public String isPass;// 是否确认
        public String isLast;// 是否为最后一条
        public boolean isReader;//消息是否已读
        public byte[] datas;// 数据字节
        public String sendIP;// 发送方 IP
        public int sendPort;// 发送方 端口
        // 字节转为为图片
        private Bitmap Bytes2Bimap(byte[] b) {
            if (b.length != 0) {
                return BitmapFactory.decodeByteArray(b, 0, b.length);
            } else {
                return null;
            }
        }
        // 将图片转为字节
        private byte[] Bitmap2Bytes(Bitmap bm) {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            bm.compress(Bitmap.CompressFormat.PNG, 100, baos);
            return baos.toByteArray();
        }
        //产生随机数并凑够6位
        private String getRandom() {
            int r = (int) (Math.random() * 1000000);
            String a = Integer.toString(r);
            return getFormatString(a, 6);
        }
        private String getFormatString(String s, int n) {
            n = n - s.length();
            for (int i = 0; i < n; i++) {
                s = "0" + s;// 为了凑够6位数
            }
            return s;
        }
    }
    View Code

    管理消息类(主要是针对发送消息过大,分批发送使用) : MessageManage.java

    package com.java.net;
    
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * 消息管理
     * */
    public class MessageManage {
    
        private MessageManage(){
            list = new ArrayList<MessageEntity>();
        }
        private static MessageManage msgm = new MessageManage();
        public static MessageManage getMessageManage(){
            return msgm;
        }
        private static List<MessageEntity> list;
        //添加
        public void add(MessageEntity me){
            if (list.size() > 0) {
                for (int i = 0; i < list.size(); i++) {
                    MessageEntity dd = list.get(i);
                    if (dd.getFlagNo().equals(me.getFlagNo())) {
                        dd.datas = addBytes(dd.datas,me.datas);
                        return;
                    }
                }
            }
            //新添加时, 如果数量大于 max则移除所有
            if (size()>MaxSize) {
                for (int i = 0; i < list.size(); i++) {
                    MessageEntity dd = list.get(i);
                    if (dd.isReader) {
                        list.remove(i);//移除已读消息
                    }
                }
            }
            list.add(me);
        }
        final int MaxSize = 500;//如果大于500条则自动清理
        //读取消息
        public MessageEntity reader(MessageEntity me){
            for (int i = 0; i < list.size(); i++) {
                MessageEntity dd = list.get(i);
                if (dd.getFlagNo().equals(me.getFlagNo())) {
                    //设置为已读
                    dd.isReader = true;
                    return dd;
                }
            }
            return null;
        }
        public static int size(){
            return list.size();
        }
        //合并两个字节数组
        public static byte[] addBytes(byte[] data1, byte[] data2) {
            byte[] data3 = new byte[data1.length + data2.length];
            System.arraycopy(data1, 0, data3, 0, data1.length);
            System.arraycopy(data2, 0, data3, data1.length, data2.length);
            return data3;
    
        }
    }
    View Code

    UDP端口发送监听类 UdpEntitiy.java 用于发送消息和监听消息

    package com.java.net;
    
    import java.io.File;
    import java.io.IOException;
    import java.net.DatagramPacket;
    import java.net.DatagramSocket;
    import java.net.InetAddress;
    import java.net.SocketException;
    import java.util.ArrayList;
    import java.util.Collection;
    import java.util.EventListener;
    import java.util.HashSet;
    import java.util.Iterator;
    import java.util.LinkedList;
    import java.util.List;
    
    import android.graphics.Bitmap;
    import android.os.Message;
    
    
    public class UdpEntitiy{
    
        private UdpEntitiy(){
        }
        private static UdpEntitiy udp = new UdpEntitiy();
        public static UdpEntitiy getUdpEntitiy(){
            return udp;
        }
        private int port = 12345;//监听端口
        private int getPortSend() {//临时端口 发送时使用
            return (port + 1);
        }
        public int getPort() {
            return port;
        }
        public void setPort(int port) {
            this.port = port;
        }
        private boolean isReceive;//是否监听
        public boolean isReceive() {
            return isReceive;
        }
        public void startReceive(){
            if (!isReceive) {//如果没有监听
                new Thread(){
                    public void run() {
                        receiveMessage();
                    };
                }.start();
            }
        }
        //发送消息
        public void send(final String ip,final MessageEntity ms){
            new Thread(){
                public void run() {
                    sendMessage(ip,ms);
                };
            }.start();
        }
        //发送文字
        public void send(final String ip,String s){
            final MessageEntity ms = new MessageEntity(s);
            send(ip,ms);
        }
        //发送图片
        public void send(final String ip,Bitmap s){
            final MessageEntity ms = new MessageEntity(s);
            send(ip,ms);
        }
        //发送文件
        public void send(final String ip,File s){
            final MessageEntity ms = new MessageEntity(s);
            send(ip,ms);
        }
        public void stopReceive(){
            if (isReceive) {//如果监听
                socket.close();
            }
        }
        //接收消息接口
        public interface ReceivesListener extends EventListener{
            //当接收到消息时
            public void onReceiveMessage(MessageEntity messageEntity);
        }
        private Collection listeners = new HashSet();
        public void onReceiveMessage(ReceivesListener receiveListener){
            if (listeners == null) {
                listeners = new HashSet();
            }
            listeners.add(receiveListener);
        }
        private void notifyListener(MessageEntity s){
            if (listeners != null) {
                Iterator iter = listeners.iterator();
                while (iter.hasNext()) {
                    ReceivesListener r = (ReceivesListener) iter.next();
                    r.onReceiveMessage(s);
                }
            }
        }
        
        DatagramSocket socket = null;//声明 数据报套接字
        final int VALUE_MAX = 2048;//接收发送最大字节 2kb
        LinkedList flags = new LinkedList();
        MessageManage msgm = MessageManage.getMessageManage();
        //监听数据接收
        private void receiveMessage(){
            try {
                socket = new  DatagramSocket(port);//初始化 数据报套接字
                isReceive = true;//设置状态 - 已经在监听
                while (true) {
                    byte data[] = new byte[VALUE_MAX];//接收存放的字节
                    DatagramPacket packet = new DatagramPacket(data, data.length);//声明初始化接收的数据包
                    //阻塞监听
                    socket.receive(packet);
                    //接收到端口数据消息
                    MessageEntity me = new MessageEntity();
                    //截获返回符
                    if (packet.getLength() == me.getFlagNo().length()) {
                        flags.add(new String(packet.getData(),packet.getOffset(),packet.getLength()));
                        continue;
                    }
                    me.sendIP = packet.getAddress().getHostAddress();
                    me.sendPort = packet.getPort();
                    //设置头部信息
                    int headSize = me.getHeadToByte().length;
                    me.resetParameter(new String(packet.getData(),packet.getOffset(),headSize), me);
                    //获取有效字节
                    byte ndata[] = new byte[packet.getLength()-headSize];
                    System.arraycopy(packet.getData(),headSize,ndata,0,ndata.length);
                    me.datas = ndata;//赋值
                    //添加到消息中
                    msgm.add(me);
                    if (me.isLast.equals("1")) {//最后一个
                        me = msgm.reader(me);
                        notifyListener(me);//通知
                    }
                }
            } catch (SocketException e) {
                //socket 关闭是会抛异常, 才可以停止消息阻塞
            } catch (IOException e) {
            }finally{
                isReceive = false;
                if (socket!=null) {
                    socket.close();
                }
            }
        }
    
        //发送
        private void sendMessage(String ip, MessageEntity ms){
            DatagramSocket ssocket = null;//声明 发送套接字
            try {
                ms.isLast = "1";//先设置为最后一个
                byte[] hd1 = ms.getHeadToByte();//已完成的头部字节
                ssocket = new  DatagramSocket (getPortSend());//初始化 发送套接字 使用临时端口
                InetAddress serverAddress = InetAddress.getByName(ip);//声明初始化 服务器地址
                //发消息是否有返回确认
                if (ms.isPass.equals("1")) {//需要确认
                    //发送确认码
                    byte[] qrm = ms.getFlagNo().getBytes();
                    DatagramPacket packet = new DatagramPacket(qrm, qrm.length, serverAddress, port);
                    ssocket.send(packet);
                    boolean qm = true;
                    while(qm){
                        if (flags.size() > 0) {
                            for (int i = 0; i < flags.size(); i++) {
                                if (flags.get(i).equals(ms.getFlagNo())) {
                                    flags.remove(i);
                                    qm = false;
                                    break;
                                }
                            }
                        }
                    }
                }
                int allLength = ms.datas.length + hd1.length;
                if (allLength <= VALUE_MAX) {//一次发送
                    byte[] sbt = addBytes(hd1,ms.datas);
                    //声明初始化 数据发送包 端口为 服务器监听端口
                    DatagramPacket packet = new DatagramPacket(sbt, sbt.length, serverAddress, port);
                    //发送
                    ssocket.send(packet);
                }else {//分次发送
                    //int n = allLength / (VALUE_MAX - hd1.length);
                    //int m = allLength % (VALUE_MAX - hd1.length);
                    //n = n + (m > 0 ? 1 : 0);
                    byte[] hd2 = ms.getHeadToByte();//未完成的头部字节
                    int n = ms.datas.length / VALUE_MAX;
                    int d = ms.datas.length % VALUE_MAX;
                    int m = n * hd2.length;
                    int c = (m + d) / VALUE_MAX;
                    int f = (m + d) % VALUE_MAX;
                    n = n + c + (f > 0 ? 1 : 0);
                    ms.isLast = "0";
                    for (int i = 0; i < n; i++) {
                        if (i == (n - 1)) {
                            byte[] nbt = new byte[m];
                            System.arraycopy(ms.datas, i * (VALUE_MAX-hd2.length), nbt, 0, nbt.length);
                            byte[] dt1 = addBytes(hd1,nbt);//未完成状态 和 字节之和
                            DatagramPacket packet = new DatagramPacket(dt1, dt1.length, serverAddress, port);
                            ssocket.send(packet);
                        }else {
                            byte[] nbt = new byte[VALUE_MAX-hd2.length];
                            System.arraycopy(ms.datas, i * (VALUE_MAX-hd2.length), nbt, 0, nbt.length);
                            byte[] dt1 = addBytes(hd2,nbt);//未完成状态 和 字节之和
                            DatagramPacket packet = new DatagramPacket(dt1, dt1.length, serverAddress, port);
                            ssocket.send(packet);
                        }
                    }
                }
            } catch (SocketException e) {
            } catch (IOException e) {
            }finally{
                if (ssocket!=null) {
                    ssocket.close();//关闭
                }
            }
        }
        //合并字节数组
        private static byte[] addBytes(byte[] data1, byte[] data2) {
            byte[] data3 = new byte[data1.length + data2.length];
            System.arraycopy(data1, 0, data3, 0, data1.length);
            System.arraycopy(data2, 0, data3, data1.length, data2.length);
            return data3;
        }
    }
    View Code

    以上是所有代码,  最简单的调用如下  实现发送接收

            UdpEntitiy udp = UdpEntitiy.getUdpEntitiy();//获取
            udp.startReceive();//开始监听
            /**
             * 监听消息
             * 当收到消息时调用
             * */
            udp.onReceiveMessage(new ReceivesListener() {
    
                @Override
                public void onReceiveMessage(MessageEntity messageEntity) {
                    // TODO Auto-generated method stub
                    Message msg = new Message();
                    msg.obj = messageEntity;
                    msgHd.sendMessage(msg);
                }
            });
            /**
             * 发送消息
             * 第一个是要发送到的IP, 第二个是消息
             * */
            udp.send(ip.getText().toString(), send.getText().toString());
    View Code

    2. 电脑版本 c#

    当类库写完之后最简单的调用如下:

    //放在窗体初始化上面
    UdpSocket.OnListenter += recive;
    InitializeComponent();//初始控件
    
    
    //加载事件
    UdpSocket.Start();//开启监听[线程]
    
    //窗体关闭事件
    UdpSocket.Close();//关闭监听[线程]
    
    //发送消息
    UdpSocket.SendMessage("目标IP地址", "消息");
    
    //定义接收消息的方法
    private void recive(MessageEntity msg) 
    {
        //消息封装在了MessageEntity中
        //通过 msg.GetString() 获取消息
    }
    View Code

    以下是全部代码:

    窗体初始化控件代码自动生成的

    namespace UdpEntity
    {
        partial class Form1
        {
            /// <summary>
            /// 必需的设计器变量。
            /// </summary>
            private System.ComponentModel.IContainer components = null;
    
            /// <summary>
            /// 清理所有正在使用的资源。
            /// </summary>
            /// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
            protected override void Dispose(bool disposing)
            {
                if (disposing && (components != null))
                {
                    components.Dispose();
                }
                base.Dispose(disposing);
            }
    
            #region Windows 窗体设计器生成的代码
    
            /// <summary>
            /// 设计器支持所需的方法 - 不要
            /// 使用代码编辑器修改此方法的内容。
            /// </summary>
            private void InitializeComponent()
            {
                this.button1 = new System.Windows.Forms.Button();
                this.textBox1 = new System.Windows.Forms.TextBox();
                this.textBox2 = new System.Windows.Forms.TextBox();
                this.textBox3 = new System.Windows.Forms.TextBox();
                this.SuspendLayout();
                // 
                // button1
                // 
                this.button1.Location = new System.Drawing.Point(378, 303);
                this.button1.Name = "button1";
                this.button1.Size = new System.Drawing.Size(75, 23);
                this.button1.TabIndex = 0;
                this.button1.TabStop = false;
                this.button1.Text = "发送";
                this.button1.UseVisualStyleBackColor = true;
                this.button1.Click += new System.EventHandler(this.button1_Click_1);
                // 
                // textBox1
                // 
                this.textBox1.BackColor = System.Drawing.Color.White;
                this.textBox1.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
                this.textBox1.Location = new System.Drawing.Point(12, 12);
                this.textBox1.Multiline = true;
                this.textBox1.Name = "textBox1";
                this.textBox1.ReadOnly = true;
                this.textBox1.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
                this.textBox1.Size = new System.Drawing.Size(441, 280);
                this.textBox1.TabIndex = 1;
                this.textBox1.TabStop = false;
                // 
                // textBox2
                // 
                this.textBox2.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
                this.textBox2.Location = new System.Drawing.Point(12, 303);
                this.textBox2.Name = "textBox2";
                this.textBox2.Size = new System.Drawing.Size(360, 21);
                this.textBox2.TabIndex = 2;
                this.textBox2.TabStop = false;
                // 
                // textBox3
                // 
                this.textBox3.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
                this.textBox3.Location = new System.Drawing.Point(12, 337);
                this.textBox3.Multiline = true;
                this.textBox3.Name = "textBox3";
                this.textBox3.Size = new System.Drawing.Size(441, 121);
                this.textBox3.TabIndex = 3;
                // 
                // Form1
                // 
                this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
                this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
                this.ClientSize = new System.Drawing.Size(472, 469);
                this.Controls.Add(this.textBox3);
                this.Controls.Add(this.textBox2);
                this.Controls.Add(this.textBox1);
                this.Controls.Add(this.button1);
                this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
                this.MaximizeBox = false;
                this.MinimizeBox = false;
                this.Name = "Form1";
                this.ShowInTaskbar = false;
                this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
                this.Text = "局域网聊天";
                this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.Form1_FormClosed);
                this.Load += new System.EventHandler(this.Form1_Load);
                this.ResumeLayout(false);
                this.PerformLayout();
    
            }
    
            #endregion
    
            private System.Windows.Forms.Button button1;
            private System.Windows.Forms.TextBox textBox1;
            private System.Windows.Forms.TextBox textBox2;
            private System.Windows.Forms.TextBox textBox3;
    
        }
    }
    View Code

    窗体后台代码

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    using System.Net;
    using System.Threading;
    using System.Diagnostics;
    
    namespace UdpEntity
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                UdpSocket.OnListenter += recive;
                InitializeComponent();
            }
    
           
    
            private void Form1_Load(object sender, EventArgs e)
            {
                UdpSocket.Start();
                textBox2.Text = "192.168.1.103";
            }
    
            private void recive(MessageEntity msg) 
            {
                textBox1.AppendText("
    消息来自: [ " + msg.sendIp + " ]
    " + msg.GetString());
            }
    
            private void Form1_FormClosed(object sender, FormClosedEventArgs e)
            {
                UdpSocket.Close();
            }
    
            private void button1_Click_1(object sender, EventArgs e)
            {
                if (textBox2.Text != "" && textBox3.Text != "")
                {
                    UdpSocket.SendMessage(textBox2.Text, textBox3.Text);
                    textBox3.Text = "";
                }
            }
        }
    }
    View Code

    封装的接收消息类库 MessageEntity.cs

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace UdpEntity
    {
        public class MessageEntity
        {
            #region 字段
            private string flagNo;
            /// <summary>
            /// 获取消息标识
            /// </summary>
            /// <returns></returns>
            public string GetFlagNo()
            {
                return flagNo;
            }
            /// <summary>
            /// 发送接收 数据类型
            /// </summary>
            public string type;
            /// <summary>
            /// 是否有返回
            /// </summary>
            public string isPass;
            /// <summary>
            /// 是否为最后一条消息
            /// </summary>
            public string isLast;
            /// <summary>
            /// 是否已读
            /// </summary>
            public bool isReader;
            /// <summary>
            /// 发送方IP
            /// </summary>
            public string sendIp;
            /// <summary>
            /// 发送方端口
            /// </summary>
            public int sendPort;
            /// <summary>
            /// 存放的数据
            /// </summary>
            public byte[] datas;
            
            #endregion
    
            #region 方法
            
            public MessageEntity()
            {
                init();
            }
            //初始化
            private void init()
            {
                flagNo = getRandom();//getRandom();// 6 位随机数
                type = "00";
                isPass = "0";
                isLast = "1";
            }
            public MessageEntity(string s)
            {
                init();
                type = "00";//字符串
                datas = Encoding.GetEncoding("UTF-8").GetBytes(s);
            }
            //根据字节获取字符串
            public string GetString()
            {
                if (datas != null && datas.Length > 0)
                {
                    return Encoding.GetEncoding("UTF-8").GetString(datas, 0, datas.Length);
                }
                return string.Empty;
            }
            //获取头字节
            public byte[] getHeadToByte()
            {
                return Encoding.GetEncoding("UTF-8").GetBytes((GetFlagNo() + "," + type + "," + isPass + "," + isLast));
            }
            //根据字节 重置头部参数
            public MessageEntity resetParameter(byte[] b, MessageEntity m)
            {
                if (m == null)
                {
                    m = new MessageEntity();
                }
                if (b != null && b.Length > 0)
                {
                    string s = Encoding.GetEncoding("UTF-8").GetString(b, 0, b.Length);
                    resetParameter(s, m);
                }
                return m;
            }
            //根据字节 重置头部参数
            public MessageEntity resetParameter(string b, MessageEntity m)
            {
                string[] ss = b.Split(',');
                if (ss.Length >= 4)
                {
                    m.flagNo = ss[0];
                    m.type = ss[1];
                    m.isPass = ss[2];
                    m.isLast = ss[3];
                }
                return m;
            }
            //产生随机数并凑够6位
            public String getRandom()
            {
                string aa = (Math.Abs(Guid.NewGuid().GetHashCode()) % 1000000).ToString();
                return getFormatString(aa, 6);
            }
            private String getFormatString(string s, int n)
            {
                n = n - s.Length;
                for (int i = 0; i < n; i++)
                {
                    s = "0" + s;// 为了凑够6位数
                }
                return s;
            }
            #endregion
        }
    }
    View Code

    消息管理类库 MessageManage.cs

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace UdpEntity
    {
        public class MessageManage
        {
            private MessageManage() { }
            private static MessageManage msgm = new MessageManage();
            public static MessageManage GetMessageManange()
            {
                return msgm;
            }
            List<MessageEntity> list = new List<MessageEntity>();
            int MaxSize = 500;//如果大于500条则自动清理
            //Buffer.BlockCopy(dst, 0, cc, src.Length, dst.Length);
            //Buffer.BlockCopy([源数组], [从源数组哪里开始, 偏移量], 
            // [目标数组] , [从目标数组哪里开始, 偏移量] , [所要复制的字节大小, 长度]);
            public byte[] CopyByte(byte[] src, byte[] dst)
            {
                byte[] cc = new byte[src.Length + dst.Length];
                Buffer.BlockCopy(src, 0, cc, 0, src.Length);
                Buffer.BlockCopy(dst, 0, cc, src.Length, dst.Length);
                return cc;
            }
            public void Add(MessageEntity me)
            {
                if (list.Count > 0)
                {
                    for (int i = 0; i < list.Count; i++)
                    {
                        MessageEntity m = list[i];
                        if (m.GetFlagNo() == me.GetFlagNo())
                        {
                            byte[] a = new byte[1];
                            byte[] b = new byte[1];
                            me.datas = CopyByte(a, b);
                            return;
                        }
                    }
                }
                //新添加时, 如果数量大于 max则移除所有
                if (size() > MaxSize)
                {
                    for (int i = 0; i < list.Count; i++)
                    {
                        MessageEntity dd = list[i];
                        if (dd.isReader)
                        {
                            list.RemoveAt(i);//移除已读消息
                        }
                    }
                }
                list.Add(me);
    
            }
            public int size()
            {
                return list.Count;
            }
            //读取消息
            public MessageEntity reader(MessageEntity me)
            {
                for (int i = 0; i < list.Count; i++)
                {
                    MessageEntity dd = list[i];
                    if (dd.GetFlagNo() == me.GetFlagNo())
                    {
                        //设置为已读
                        dd.isReader = true;
                        return dd;
                    }
                }
                return null;
            }
        }
    }
    View Code

    UDP发送接收监听代码 UdpSocket.cs

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading;
    using System.Net;
    using System.Net.Sockets;
    
    namespace UdpEntity
    {
        public static class UdpSocket
        {
            //本机名称和IP
            public static string ComputerName;
            public static string ComputerIP;
            public const int listenProt = 12345;//设置端口号
            static UdpClient listener = null;//提供的网络服务
            static Thread listenter = null;//创建一个监听消息的进程
            static bool islistenter;//是否要监听
            static bool isconn;//是否已经在监听
            public static bool IsMsgReader;//消息是否已读
    
            public static void Start()
            {
                if (listenter == null || isconn)
                {
                    listenter = new Thread(StartListener);
                    listenter.Start();
                }
            }
    
            static UdpSocket()
            {
                isconn = false;
                IsMsgReader = true;
                ComputerName = Dns.GetHostName();
                ComputerIP = GetIPAddress();
                islistenter = true;
                //加下面这句是为了在开启线程中可以访问控件属性
                System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = false;
                //OnListenter = Listenter;
            }
            //关闭
            public static void Close()
            {
                if (listener == null)
                {
                    return;
                }
                try
                {
                    isconn = false;
                    listener.Close();//关闭探听消息服务
                    listenter.Abort();//关闭监听消息进程
                }
                catch { }
            }
            //获取IP
            public static string GetIPAddress()
            {
                string AddressIP = "";
                //第一种办法获取
                foreach (IPAddress _IPAddress in Dns.GetHostEntry(Dns.GetHostName()).AddressList)
                {
                    if (_IPAddress.AddressFamily.ToString().ToLower() == "internetwork")
                    {
                        //System.Windows.Forms.MessageBox.Show(_IPAddress.AddressFamily.ToString().ToLower()  + " - " + _IPAddress.ToString());
                        //return _IPAddress.ToString();
                    }
                }
                //第二种办法获取
                if (AddressIP == "")
                {
                    IPHostEntry myEntry = Dns.GetHostEntry(System.Net.Dns.GetHostName());
                    if (myEntry.AddressList.Length > 1)
                    {
                        if (myEntry.AddressList[0].ToString().IndexOf('.') > 0)
                        {
                            AddressIP = myEntry.AddressList[0].ToString();
                        }
                        else
                        {
                            AddressIP = myEntry.AddressList[1].ToString();
                        }
                        AddressIP = myEntry.AddressList[1].ToString();
                    }
                    else
                    {
                        AddressIP = myEntry.AddressList[0].ToString();
                    }
                }
                return AddressIP;
            }
            public delegate void Listenter(MessageEntity msg);
            public static event Listenter OnListenter;
            static List<string> lis = new List<string>();
            static MessageManage msgm = MessageManage.GetMessageManange();
            /// <summary>
            /// 截取数组
            /// </summary>
            /// <param name="src">原始数组</param>
            /// <param name="t">开始下标</param>
            /// <param name="p">截取多长</param>
            /// <returns></returns>
            private static byte[] CutByte(byte[] src, int t, int p) 
            {
                byte[] n = new byte[p];
                Buffer.BlockCopy(src, t, n, 0, n.Length);
                return n;
            }
            //开始监听
            private static void StartListener()
            {
                if (isconn == true)//已经开启监听就不要在开启了
                {
                    return;
                }
                try
                {
                    isconn = true;
                    listener = new UdpClient(listenProt); //使用UDP协议
                    IPEndPoint groupEP = new IPEndPoint(IPAddress.Any, listenProt); //任意IP,
                    while (islistenter)//处于监听状态
                    {
                        byte[] bytes = listener.Receive(ref groupEP);
                        MessageEntity me = new MessageEntity();
                        //如果接收字节大小等于 标识字节大小
                        if (Encoding.GetEncoding("UTF-8").GetBytes(me.GetFlagNo()).Length == bytes.Length)
                        {
                            lis.Add(Encoding.GetEncoding("UTF-8").GetString(bytes, 0, bytes.Length));
                            continue;
                        }
                        me.sendIp = groupEP.Address.ToString();//发送人的IP
                        me.sendPort = groupEP.Port;//发送人的端口号
    
                        byte[] hd = CutByte(bytes, 0, me.getHeadToByte().Length);//头部字节
                        me = me.resetParameter(hd, me);//赋值
                        me.datas = CutByte(bytes, me.getHeadToByte().Length, bytes.Length - hd.Length);//数据字节
                        msgm.Add(me);
                        if (me.isLast == "1")
                        {
                            me = msgm.reader(me);
                            if (OnListenter != null)
                            {
                                OnListenter(me);
                            }
                        }
                    }
                }
                catch {
                }
                finally
                {
                    isconn = false;
                    if (listener!=null)
                    {
                        listener.Close();
                    }
                }
            }
            static int VALUE_MAX = 2048;//接收发送最大字节 2kb
            public static void SendMessage(string ipStr, string msg)
            {
                MessageEntity me = new MessageEntity(msg);
                SendMessage(ipStr, me);
            }
            public static void SendMessage(string ipStr, MessageEntity me)
            {
                Send(ipStr, me);
            }
            /// <summary>
            /// 发送消息 string
            /// </summary>
            /// <param name="ipStr">IP</param>
            /// <param name="me">消息</param>
            private static void Send(string ipStr, MessageEntity me)
            {
                Socket s = new Socket(AddressFamily.InterNetwork,
                        SocketType.Dgram, ProtocolType.Udp);
                try
                {
                    IPAddress broadcast = IPAddress.Parse(ipStr);
                    IPEndPoint ep = new IPEndPoint(broadcast, listenProt);
                    me.isLast = "0";//未成功
                    byte[] hd = me.getHeadToByte();//未完成
                    me.isLast = "1";//最后一次
                    byte[] shd = me.getHeadToByte();//已完成
                    if (me.isPass == "1")
                    {//需要确认
                        //发送确认码
                        byte[] qrm = Encoding.GetEncoding("UTF-8").GetBytes(me.GetFlagNo());
                        s.SendTo(qrm, ep);
    
                        bool qm = true;
                        while (qm)
                        {
                            if (lis.Count > 0)
                            {
                                for (int i = 0; i < lis.Count; i++)
                                {
                                    if (lis[i] == me.GetFlagNo())
                                    {
                                        lis.RemoveAt(i);
                                        qm = false;
                                        break;
                                    }
                                }
                            }
                        }
                    }
                    int an = hd.Length + me.datas.Length;//总长度
                    if (an <= VALUE_MAX)//字节小于
                    {
                        byte[] pj = msgm.CopyByte(shd, me.datas);
                        s.SendTo(pj, ep);
                    }
                    else//分次发送
                    {
                        //byte[] hd2 = ms.getHeadToByte();//未完成的头部字节
                        int n = me.datas.Length / VALUE_MAX;
                        int d = me.datas.Length % VALUE_MAX;
                        int m = n * hd.Length;
                        int c = (m + d) / VALUE_MAX;
                        int f = (m + d) % VALUE_MAX;
                        n = n + c + (f > 0 ? 1 : 0);
    
                        for (int i = 0; i < n; i++)
                        {
                            if (i == (n - 1))
                            {
                                byte[] nbt = new byte[f - shd.Length];
                                nbt = CutByte(me.datas, i * (VALUE_MAX - hd.Length), nbt.Length);
                                s.SendTo(msgm.CopyByte(shd, nbt), ep);
                            }
                            else
                            {
                                byte[] nbt = new byte[VALUE_MAX - hd.Length];
                                nbt = CutByte(me.datas, i * (VALUE_MAX - hd.Length), nbt.Length);
                                s.SendTo(msgm.CopyByte(hd, nbt), ep);
                            }
                        }
                    }
                }
                catch { }
                finally
                {
                    s.Close();
                }
            }
        }
    }
    View Code

    不过用处不大, 实用性很小, 感谢大家百忙之中来抽空看.^.^

  • 相关阅读:
    回溯法(背包问题和八皇后问题)
    wxidgets知识点
    计算机组成原理十套练习-白中英(B1 B2 B3 B4 B5 B6 B7B8 B9 B10)
    mbed sdk结构
    CC2540/2541软件开发指南
    GNU Utility
    迭代(iterate)和递归(recursion)的区别
    最长回文子串的求解(java)
    1、surrounded-regions
    mvn compile 出错 [ERROR] 不再支持源选项 1.5。请使用 1.6 或更高版本。
  • 原文地址:https://www.cnblogs.com/weloglog888/p/7676409.html
Copyright © 2011-2022 走看看