Android手机版和电脑版 效果图: 通过WiFi局域网 电脑和手机连接通信. 电脑版本和手机版本使用了相同的消息发送头协议, 可以相互接收消息. 若有做的不好的地方还希望大家指导一下.
1. 手机版
添加权限 AndroidManifest.xml
<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 可要可不要
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.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;
}
}
管理消息类(主要是针对发送消息过大,分批发送使用) : 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; }
}
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(, );
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(, );
this.button1.TabIndex = ;
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(, );
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(, );
this.textBox1.TabIndex = ;
this.textBox1.TabStop = false;
//
// textBox2
//
this.textBox2.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.textBox2.Location = new System.Drawing.Point(, );
this.textBox2.Name = "textBox2";
this.textBox2.Size = new System.Drawing.Size(, );
this.textBox2.TabIndex = ;
this.textBox2.TabStop = false;
//
// textBox3
//
this.textBox3.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.textBox3.Location = new System.Drawing.Point(, );
this.textBox3.Multiline = true;
this.textBox3.Name = "textBox3";
this.textBox3.Size = new System.Drawing.Size(, );
this.textBox3.TabIndex = ;
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(, );
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 = "";
isPass = "";
isLast = "";
}
public MessageEntity(string s)
{
init();
type = "";//字符串
datas = Encoding.GetEncoding("UTF-8").GetBytes(s);
}
//根据字节获取字符串
public string GetString()
{
if (datas != null && datas.Length > )
{
return Encoding.GetEncoding("UTF-8").GetString(datas, , 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 > )
{
string s = Encoding.GetEncoding("UTF-8").GetString(b, , b.Length);
resetParameter(s, m);
}
return m;
}
//根据字节 重置头部参数
public MessageEntity resetParameter(string b, MessageEntity m)
{
string[] ss = b.Split(',');
if (ss.Length >= )
{
m.flagNo = ss[];
m.type = ss[];
m.isPass = ss[];
m.isLast = ss[];
}
return m;
}
//产生随机数并凑够6位
public String getRandom()
{
string aa = (Math.Abs(Guid.NewGuid().GetHashCode()) % ).ToString();
return getFormatString(aa, );
}
private String getFormatString(string s, int n)
{
n = n - s.Length;
for (int i = ; i < n; i++)
{
s = "" + 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条则自动清理
//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, , cc, , src.Length);
Buffer.BlockCopy(dst, , cc, src.Length, dst.Length);
return cc;
}
public void Add(MessageEntity me)
{
if (list.Count > )
{
for (int i = ; i < list.Count; i++)
{
MessageEntity m = list[i];
if (m.GetFlagNo() == me.GetFlagNo())
{
byte[] a = new byte[];
byte[] b = new byte[];
me.datas = CopyByte(a, b);
return;
}
}
}
//新添加时, 如果数量大于 max则移除所有
if (size() > MaxSize)
{
for (int i = ; 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 = ; 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 = ;//设置端口号
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 > )
{
if (myEntry.AddressList[].ToString().IndexOf('.') > )
{
AddressIP = myEntry.AddressList[].ToString();
}
else
{
AddressIP = myEntry.AddressList[].ToString();
}
AddressIP = myEntry.AddressList[].ToString();
}
else
{
AddressIP = myEntry.AddressList[].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, , 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, , bytes.Length));
continue;
}
me.sendIp = groupEP.Address.ToString();//发送人的IP
me.sendPort = groupEP.Port;//发送人的端口号 byte[] hd = CutByte(bytes, , 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 == "")
{
me = msgm.reader(me);
if (OnListenter != null)
{
OnListenter(me);
}
}
}
}
catch {
}
finally
{
isconn = false;
if (listener!=null)
{
listener.Close();
}
}
}
static int VALUE_MAX = ;//接收发送最大字节 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 = "";//未成功
byte[] hd = me.getHeadToByte();//未完成
me.isLast = "";//最后一次
byte[] shd = me.getHeadToByte();//已完成
if (me.isPass == "")
{//需要确认
//发送确认码
byte[] qrm = Encoding.GetEncoding("UTF-8").GetBytes(me.GetFlagNo());
s.SendTo(qrm, ep); bool qm = true;
while (qm)
{
if (lis.Count > )
{
for (int i = ; 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 > ? : ); for (int i = ; i < n; i++)
{
if (i == (n - ))
{
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();
}
}
}
}
不过用处不大, 实用性很小, 感谢大家百忙之中来抽空看.^.^