Android手機版和電腦版 效果圖: 經過WiFi局域網 電腦和手機鏈接通訊. 電腦版本和手機版本使用了相同的消息發送頭協議, 能夠相互接收消息. 如有作的很差的地方還但願你們指導一下.java
1. 手機版android
添加權限 AndroidManifest.xmlc#
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
頁面 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>
後臺代碼 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() + "\n");
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() + "\n");
}
};
};
}
如下是類庫代碼:網絡
獲取IP地址 IPUtils.java 可要可不要app
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; } } }
發送接收消息包裝類庫 :MessageEntity.javadom
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; } }
管理消息類(主要是針對發送消息過大,分批發送使用) : MessageManage.javasocket
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; } }
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; } }
以上是全部代碼, 最簡單的調用以下 實現發送接收
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());
2. 電腦版本 c#
當類庫寫完以後最簡單的調用以下:
//放在窗體初始化上面 UdpSocket.OnListenter += recive; InitializeComponent();//初始控件 //加載事件 UdpSocket.Start();//開啓監聽[線程] //窗體關閉事件 UdpSocket.Close();//關閉監聽[線程] //發送消息 UdpSocket.SendMessage("目標IP地址", "消息"); //定義接收消息的方法 private void recive(MessageEntity msg) { //消息封裝在了MessageEntity中 //經過 msg.GetString() 獲取消息 }
如下是所有代碼:
窗體初始化控件代碼自動生成的
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; } }
窗體後臺代碼
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("\r\n消息來自: [ " + msg.sendIp + " ]\r\n" + 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 = ""; } } } }
封裝的接收消息類庫 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 } }
消息管理類庫 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; } } }
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(); } } } }
不過用處不大, 實用性很小, 感謝你們百忙之中來抽空看.^.^