C#实战之CAD二次开发006:与python进行Socket传输文件

前言
前面介绍了与CAD相关的一些功能,本期介绍一下C#和python如何通过socket通信来进行文件的传输,建议不了解Socket的同学先去了解一下socket的通讯原理,这样看起来不会云里雾里的。

一、C#端(服务端)

C#端使用的Socket基于TCP协议,首先我们定义一个Socket对象,记得要添加引用
using System.Net.Sockets;
using System.Net;

Socket serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

然后在设置绑定的ip及端口,ip为本机ip,端口设置成你所需要的即可。

serverSocket.Bind(new IPEndPoint(IPAddress.Parse("10.148.88.192"), 8888));

接下来就是设置监听数量

serverSocket.Listen(5);

最后就是等待客户端发送请求过来,当接收到请求后,就会调用send_file()方法,自动打开CAD,并生成一些图块,文字,标注(之前所介绍过的),然后打印成pdf文件,并且将打印出的pdf文件发送给python客户端。

while (true)
{
    Socket client = serverSocket.Accept();
    string str = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
    Console.WriteLine("[INFO]:" + str);
    send_file(client);
    //顯示請求的ip地址
    IPAddress adress = ((IPEndPoint)client.RemoteEndPoint).Address;
    string ip = adress.ToString();
    Console.WriteLine("[INFO]:收到請求!" + ip);
}

下面贴上send_file方法的代码,里面主要包含了打开CAD文档,执行打印pdf功能,将生成好的pdf文件发送给客户端。

private static void send_file(Socket client)
{
    object[] obj = openCad();
    if (null == obj)
    {
        Console.WriteLine("[ERROR]:Cad啟動失敗");
    }
    // 获取App对象和Doc对象
    AcadApplication App = (AcadApplication)obj[0];
    AcadDocument Doc = (AcadDocument)obj[1];
    try
    {
        // 发送cad命令
        Doc.SendCommand("(command " + "\"" + "cad" + "\"" + " (handent " + "\"" + "\")) ");
    }
    catch (System.Runtime.InteropServices.COMException e)
    {
        Console.WriteLine("[ERROR]:發送命令到cad時發生異常" + e.Message);
    }
    if (plotPdf(Doc, new double[] { 0, 0, 0 }, new double[] { 90, 297, 0 }) == false)
    {
        Console.WriteLine("[ERROR]:打印pdf失敗\n");
    }
    Doc.SaveAs(Application.StartupPath + "\\" + "123.dwg");
    Doc.Close();
    App.Quit();
    if (File.Exists(@"C:\Users\F1655392.SZYZ\Documents\PDF 檔案\自動儲存\"))
    {
        byte[] png1 = packFile(Application.StartupPath + "\\" + "source-逃料圖.png", true);
        client.Send(png1, SocketFlags.None);
        Console.WriteLine("[INFO]:pdf發送完成");
    }
    if (File.Exists(Application.StartupPath + "\\" + "123.dwg"))
    {
        byte[] dwg = packFile(Application.StartupPath + "\\" + "123.dwg", true);
        client.Send(dwg, SocketFlags.None);
        Console.WriteLine("[INFO]:CAD圖檔發送完成");
    }
    // 最后发送一句话本次发送文件成功
    byte[] arr3 = packMessage("本次发送成功", true);
    client.Send(arr3, SocketFlags.None);
}

openCad()方法实现打开项目目录下的source.dwg文档,并将AcadApplication对象和AcadDocument对象存到数组中并回传。

private static object[] openCad()
 {
     AcadApplication App = null;
     AcadDocument Doc = null;
     try
     {
         App = (AcadApplication)System.Runtime.InteropServices.Marshal.GetActiveObject("AutoCad.Application");
     }
     catch
     {
         try
         {
             App = new AcadApplication();
         }
         catch
         {
             return null;
         }
     }
     App.Visible = true;
     App.Documents.Close();//關閉默認打開的Drawing1.dwg文檔
     Doc = App.Documents.Open(Application.StartupPath + "\\" + "source.dwg");
     App.ZoomExtents();//使圖檔大小自適應窗口
     object[] arr = new object[2];
     arr[0] = App;
     arr[1] = Doc;
     return arr;
 }

下面重点来了,在发送文件过程中遇到了一些坑,就是在发送文件的时候会出现粘包现象,客户端在接收完第一个文件之后,接收第二个文件就会不完整,这是因为连续发送两个文件过去,导致在接收过程中客户端不知道什么时候接收完,而且我们项目发送的文件很小只有几百kb而已,也会出现粘包的问题。之前有试过设置暂停时间来隔开发送,但是电脑性能不同,暂停的时间不好控制,而且这样治标不治本。
那么应该如何解决呢?通过度娘的寻找,找到了一个解决方法,在发送文件的时候,把文件的长度和文件一起打包发送给客户端,客户端根据文件大小来接收文件,直到接收完毕为止,这样就不会出现所谓的粘包现象了。
C#端打包文件和打包信息的代码如下:

public static byte[] packFile(string filePath, bool result)
{
    byte[] file = File.ReadAllBytes(filePath);
    byte[] fileLength = BitConverter.GetBytes(file.Length);
    byte[] res = BitConverter.GetBytes(result);
    Console.WriteLine("[INFO]:文件大小" + file.Length);
    return fileLength.Concat(res).Concat(file).ToArray();
}
public static byte[] packMessage(string message, bool result)
{
    byte[] file = Encoding.UTF8.GetBytes(message);
    byte[] fileLength = BitConverter.GetBytes(file.Length);
    byte[] res = BitConverter.GetBytes(result);
    Console.WriteLine("[INFO]:結束信息大小" + file.Length);
    return fileLength.Concat(res).Concat(file).ToArray();
}

二、python端(客户端)

python端的socket通讯相对比较简单,这里直接把代码贴上

def gen_dwg(file_name):
    sk = socket.socket()  # 创建一个socket对象
    sk.connect(('10.148.88.192', 8888))  # 连接服务端ip 
	message = '请生成PDF文件'
    sk.send(bytes(message, encoding='utf-8'))
        
    f_head = sk.recv(5)
    file_size, result = struct.unpack('i?', f_head)
    buff_size = 1024
    if result:
        with open('C:\\Users\\F1655392.SZYZ\\Desktop\\source.dwg', 'wb') as fp:
            rest_size = file_size
            while 1:
                if rest_size > buff_size:
                    file_data = sk.recv(buff_size)
                else:
                    file_data = sk.recv(rest_size)
                if not file_data:
                    break
                fp.write(file_data)
                rest_size = rest_size - len(file_data)
                if rest_size == 0:
                    break
            print("[INFO:]pdf生成成功!")
    else:
        message = sk.recv(file_size)
        print(message.decode('utf8'))

这里需要注意的地方就是,我们需要将C#服务端打包发送过来的数据进行解包

file_size, result = struct.unpack('i?', f_head)

file_size就是文件的大小,result就是文件,然后就是不断接收直到接收的字节等于file_size,这样粘包的问题就得到了解决。

写到这里,CAD二次开发的基本功能就介绍到这里了,当然CAD二次开发的功能远不止这些,具体可参考这本书,里面有很多关于CAD二次开发的功能介绍。

AutoCAD VBA&VB.NET开发基础与实例教程(第二版)

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值