c# c++ 结构化传输
2015-01-06 11:37:05 bianchdaiw 阅读数 507




在c++中定义字符串类型一般是char* 或者 char[],在c#中不能直接用char接受,在c# 中 char占2个字节,而c++占1个字节。也不能直接用byte类型去接。byte虽然占1个字节,但是是无符号类型。所以必须用sbyte去接。


</pre><p></p><p></p><p><pre name="code" class="csharp">public string SbyteArrayToString(sbyte[] data){

		byte[] bytes=SbyteToByte(data);
		string ss=	 Encoding.Default.GetString(bytes);
		return ss;
	}



public byte[] SbyteToByte(sbyte [] sd){

		byte[] dest = Array.ConvertAll(sd, (a) => (byte)a);
		return dest;
	}


2007-07-17 00:22:00 BlueDog 阅读数 4332
 
结构化存储C#类库
 
官方下载:见本博客左侧栏Gmaile Drive的下载方式
CSDN下载地址:
http://download.csdn.net/source/211119
结构化存储不知什么原因,大家用得很少,我想可能是因为它很难用?太多的参数,太复杂的调用,太多要注意的地方。但是它真的很有用,为什么有用,呵呵,连EXCEL文件都是一个结构化文档,你说有没有用,不信的话,你可以用VC6.0中提供的DocView工具来查看一个EXCEL文件(名称中不能有空格)。
.net的运行库也没有提供这个功能,但实际上我想MS是有这个打算的,但不知道为什么它没有实作出来,也许对于MS的牛牛来说觉得太容易,以致于懒得去做?不过你可以看到在一些底层的命名空间里是有相关资料的。
好了,费话不多说,来看看这个类库的介绍
同样,本类库属于ExpertLib Designer Tool中,它的命名空间是ExpertLib.IO.Storage,里面主要包括以下几个类
StorageFile:用于创建和打开结构化文档
Storage:表示一个存储对象(相当于文件系统中的目录)
StorageStream:表示一个流对象(相当于文件系统中的文件)
具体的使用方法可以看示例代码
 
2012-07-19 09:38:47 onelight1997 阅读数 3046

如果传送的图片是readonly,可以通过FileInfo.IsReadOnly = false先屏蔽readonly,不然本文代码会出现小错误:

Client Code:

 

using System;

 

using System.Collections.Generic;

 

using System.Text;

 

using System.Net;

 

using System.Net.Sockets;

 

using System.IO;

 

class Program

 

{

static void Main(string[] args)

{

SendImageToServer("image.jpg");

}

static void SendImageToServer(string imgURl)

{

if (!File.Exists(imgURl)) return;

FileStream fs = File.Open(imgURl, FileMode.Open);

byte[] fileBytes = new byte[fs.Length];

using (fs)

{

fs.Read(fileBytes, 0, fileBytes.Length);

fs.Close();

}

IPAddress address = IPAddress.Parse("127.0.0.1");

TcpClient client = new TcpClient();

client.Connect(address, 8000);

using (client)

{

NetworkStream ns = client.GetStream();

using (ns)

{

ns.Write(fileBytes, 0, fileBytes.Length);

}

}

}

}

Server code:

 

using System;

 

using System.Collections.Generic;

 

using System.Text;

 

using System.Net;

 

using System.Net.Sockets;

 

using System.IO;

 

using System.Drawing;

 

using System.Drawing.Imaging;

 

class Program

 

{

static TcpClient client;

static FileStream fs = new FileStream("image.jpg", FileMode.Create);

static int bufferlength = 200;

static byte[] buffer = new byte[bufferlength];

static NetworkStream ns;

static void Main(string[] args)

{

ConnectAndListen();

}

static void ConnectAndListen()

{

TcpListener listener = new TcpListener(IPAddress.Any, 8000);

listener.Start();

while (true)

{

Console.WriteLine("wait for connecting...");

client = listener.AcceptTcpClient();

Console.WriteLine("connected");

ns = client.GetStream();

if (ns.DataAvailable)

{

ns.BeginRead(buffer, 0, bufferlength, ReadAsyncCallBack, null);

}

}

}

static void ReadAsyncCallBack(IAsyncResult result)

{

int readCount;

readCount = client.GetStream().EndRead(result);

if (readCount < 1)

{

client.Close();

ns.Dispose();

fs.Dispose();

return;

}

fs.Write(buffer, 0, readCount);

ns.BeginRead(buffer, 0, 200, ReadAsyncCallBack, null);

}

}

 

2009-11-18 13:58:00 guoliwang 阅读数 1894

 

 

服务器:

2019-03-13 12:09:54 cs1715110122 阅读数 186

最近的项目在做socket通信报文解析的时候,用到了结构体与字节数组的转换;由于客户端采用Python开发,服务端采用C#开发,所以双方必须保证各自定义结构体成员类型和长度一致才能保证报文解析的正确性,这一点非常重要。

首先是结构体定义

    [StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
    public struct DataPack
    {
        public int weldNum;
        public float x;
        public float y;
        public float z;
        //字符串,SizeConst为字符串的最大长度
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)]
        public string timeStamp;
        //结构体里的构造函数必须是带参数的
        public DataPack(int n, float x, float y, float z, string t)
        {
            weldNum = n;
            this.x = x;
            this.y = y;
            this.z = z;
            timeStamp = t;
        }
    }

需要说明的是:

1.[StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]

公共语言运行库利用StructLayoutAttribute控制类或结构的数据字段在托管内存中的物理布局,即类或结构需要按某种方式排列。如果要将类传递给需要指定布局的非托管代码,则显式控制类布局是重要的。

1)LayoutKind.Sequential:CLR对struct的Layout的处理方法与C/C++中默认的处理方式相同,即按照结构中占用空间最大的成员进行对齐(Align);

2)LayoutKind.Explicit:CLR不对结构体进行任何内存对齐(Align);

3)LayoutKind.Auto:CLR会对结构体中的字段顺序进行调整,使实例占有尽可能少的内存,并进行4byte的内存对齐(Align)

2.[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)]

结构体中每个成员的长度都是需要明确的,因为内存需要根据这个分配空间,这里我们需要在成员声明时进行定义;

string类型实际为Char[20]长度的数组,实际使用中只能有效的使用前19个字符,因为char[20]最后一位默认\0;

其次,

结构体与字节数组的互转

        //// <summary>
        /// 结构体转byte数组
        /// </summary>
        /// <param name="structObj">要转换的结构体</param>
        /// <returns>转换后的byte数组</returns>
        public static byte[] StructToBytes(object structObj)
        {
            //得到结构体的大小
            int size = Marshal.SizeOf(structObj);
            //创建byte数组
            byte[] bytes = new byte[size];
            //分配结构体大小的内存空间
            IntPtr structPtr = Marshal.AllocHGlobal(size);
            //将结构体拷到分配好的内存空间
            Marshal.StructureToPtr(structObj, structPtr, false);
            //从内存空间拷到byte数组
            Marshal.Copy(structPtr, bytes, 0, size);
            //释放内存空间
            Marshal.FreeHGlobal(structPtr);
            //返回byte数组
            return bytes;
        }

        /// <summary>
        /// byte数组转结构体
        /// </summary>
        /// <param name="bytes">byte数组</param>
        /// <param name="type">结构体类型</param>
        /// <returns>转换后的结构体</returns>
        public static object BytesToStuct(byte[] bytes, Type type)
        {
            //得到结构体的大小
            int size = Marshal.SizeOf(type);
            //byte数组长度小于结构体的大小
            if (size > bytes.Length)
            {
                //返回空
                return null;
            }
            //分配结构体大小的内存空间
            IntPtr structPtr = Marshal.AllocHGlobal(size);
            //将byte数组拷到分配好的内存空间
            Marshal.Copy(bytes, 0, structPtr, size);
            //将内存空间转换为目标结构体
            object obj = Marshal.PtrToStructure(structPtr, type);
            //释放内存空间
            Marshal.FreeHGlobal(structPtr);
            //返回结构体
            return obj;
        }

 最后,

Socket服务器与客户端,使用的是异步非阻塞的方式

服务器

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

//额外导入的两个命名空间
using System.Net.Sockets;
using System.Net;

namespace SocketServer
{
    class Program
    {
        /// <summary>
        /// Socket Server 演示
        /// </summary>
        /// <param name="args"></param>
        static void Main(string[] args)
        {
            //创建一个新的Socket,这里我们使用最常用的基于TCP的Stream Socket(流式套接字)
            var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            //将该socket绑定到主机上面的某个端口
            //方法参考:http://msdn.microsoft.com/zh-cn/library/system.net.sockets.socket.bind.aspx
            socket.Bind(new IPEndPoint(IPAddress.Any, 4530));

            //启动监听,并且设置一个最大的队列长度
            //方法参考:http://msdn.microsoft.com/zh-cn/library/system.net.sockets.socket.listen(v=VS.100).aspx
            socket.Listen(4);

            //开始接受客户端连接请求
            //方法参考:http://msdn.microsoft.com/zh-cn/library/system.net.sockets.socket.beginaccept.aspx
            socket.BeginAccept(new AsyncCallback(ClientAccepted), socket);


            Console.WriteLine("Server is ready!");
            Console.Read();
        }


        public static void ClientAccepted(IAsyncResult ar)
        {

            var socket = ar.AsyncState as Socket;

            //这就是客户端的Socket实例,我们后续可以将其保存起来
            var client = socket.EndAccept(ar);

            //给客户端发送一个欢迎消息
            client.Send(Encoding.Unicode.GetBytes("Hi there, I accept you request at " + DateTime.Now.ToString()));


            //实现每隔两秒钟给服务器发一个消息
            //这里我们使用了一个定时器
            var timer = new System.Timers.Timer();
            timer.Interval = 2000D;
            timer.Enabled = true;
            timer.Elapsed += (o, a) =>
            {
                //检测客户端Socket的状态
                if(client.Connected)
                {
                    try
                    {
                        client.Send(Encoding.Unicode.GetBytes("Message from server at " + DateTime.Now.ToString()));
                    }
                    catch(SocketException ex)
                    {
                        Console.WriteLine(ex.Message);
                    }
                }
                else
                {
                    timer.Stop();
                    timer.Enabled = false;
                    Console.WriteLine("Client is disconnected, the timer is stop.");
                }
            };
            timer.Start();


            //接收客户端的消息(这个和在客户端实现的方式是一样的)
            client.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveMessage), client);

            //准备接受下一个客户端请求
            socket.BeginAccept(new AsyncCallback(ClientAccepted), socket);
        }

        static byte[] buffer = new byte[1024];

        public static void ReceiveMessage(IAsyncResult ar)
        {

            try
            {
                var socket = ar.AsyncState as Socket;

                //方法参考:http://msdn.microsoft.com/zh-cn/library/system.net.sockets.socket.endreceive.aspx
                var length = socket.EndReceive(ar);
                //读取出来消息内容
                var message = Encoding.Unicode.GetString(buffer, 0, length);
                //显示消息
                Console.WriteLine(message);

                //接收下一个消息,递归的调用
                socket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveMessage), socket);
            }
            catch(Exception ex){
                Console.WriteLine(ex.Message);
            }
        }
    }
}

客户端 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

//导入的命名空间
using System.Net.Sockets;

namespace SocketClient
{
    class Program
    {
        /// <summary>
        /// Socket Client 演示
        /// </summary>
        /// <param name="args"></param>
        static void Main(string[] args)
        {
            //创建一个Socket
            var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            //连接到指定服务器的指定端口
            //方法参考:http://msdn.microsoft.com/zh-cn/library/system.net.sockets.socket.connect.aspx
            socket.Connect("localhost", 4530);
            Console.WriteLine("connect to the server");

            //实现接受消息的方法

            //方法参考:http://msdn.microsoft.com/zh-cn/library/system.net.sockets.socket.beginreceive.aspx
            socket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveMessage), socket);

            //接受用户输入,将消息发送给服务器端
            while(socket.Connected)
            {
                var message = "Message from client : " + DateTime.Now.ToString();//Console.ReadLine();
                var outputBuffer = Encoding.Unicode.GetBytes(message);
                socket.BeginSend(outputBuffer, 0, outputBuffer.Length, SocketFlags.None, null, null);
            }

        }


        static byte[] buffer = new byte[1024];

        public static void ReceiveMessage(IAsyncResult ar)
        {
            try
            {
                var socket = ar.AsyncState as Socket;

                //方法参考:http://msdn.microsoft.com/zh-cn/library/system.net.sockets.socket.endreceive.aspx
                var length = socket.EndReceive(ar);
                //读取出来消息内容
                var message = Encoding.Unicode.GetString(buffer, 0, length);
                //显示消息
                Console.WriteLine(message);

                //接收下一个消息,递归的调用
                socket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveMessage), socket);
            }
            catch(Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }
    }
}

参考:

https://www.cnblogs.com/dafanjoy/p/7818126.html

http://www.cnblogs.com/chenxizhang/archive/2011/09/10/2172994.html

https://docs.microsoft.com/zh-cn/dotnet/framework/network-programming/socket-code-examples?view=netframework-4.7.2

c# socket 传输文件

阅读数 3004

没有更多推荐了,返回首页