为什么C#和Python要屡屡进行混合编程呢?之前我们提到了使用托管C++封装Python的核心库为一个托管dll,然后供C#调用的途径,这种方式算是一种比较科学的方式。但是它仍然有两个小的问题,一来,我们是封装了Win平台的Python,使用的是托管C++,这就侧面说明了这个托管dll是服从于.NET Framework的,而.NET Framework和Windows绑定。二来,我们如果通过源代码的形式来调用Python,那么Python简易方便的编码特性就会完全丢失。总结下来就是两个缺点
1.无法跨平台
2.无法进行优雅的编程
3.进行类型转换的时候比较麻烦
么提到混合编程,还是有非常多的方式的,这里的话,我们实现一种最基本的方式,案例就采用C#和Python。
这种方式就是通过一种传输渠道,可以是文件,也可以是任何的通信渠道。(不管什么渠道,它们都有一个特性,即它们的规范和实现它们的语言没有任何关系)。此处我就可以通过socket来实现,如果是socket实现,那么很好的解决了跨平台和简易编程的问题(此处的简易编程指的是,如果我们通过封装源代码的形式来调用,则完全抛弃了语言的语法)
socket适用于很多不同的语言之间,现在我们尝试用C#和Python来进行普通的交流
默认C#是服务端而Python是客户端
class PyTransfer {
//和Python语言进行socket通信
//communicate with Python by socket
Socket server; //服务器套接字
Socket client; //用户套接字
IPAddress ip;
int port; //服务端ip和端口号
}
先声明出我们需要的内容,随后我们需要知道以太网的ip地址,也就是本地服务器的ip地址
public static string GetHostIP()
{
string ret = "";
IPAddress[] ips = Dns.GetHostEntry(Dns.GetHostName()).AddressList;
foreach (IPAddress ip in ips)
{
if (ip.AddressFamily == AddressFamily.InterNetwork)
{
ret = ip.MapToIPv4().ToString();
}
}
if (ret == "")
{
return null;
}
return ret;
}
写了一个比较简单的函数去实现,更多的内容可以参考计算机网络
然后是构造器当中的内容
class PyTransfer {
//和Python语言进行socket通信
//communicate with Python by socket
Socket server; //服务器套接字
Socket client; //用户套接字
IPAddress ip;
int port; //服务端ip和端口号
public PyTransfer(string address,int port) {
server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
ip = IPAddress.Parse(address);
this.port = port;
server.Bind(new IPEndPoint(ip,port));
}
public static string GetHostIP()
{
string ret = "";
IPAddress[] ips = Dns.GetHostEntry(Dns.GetHostName()).AddressList;
foreach (IPAddress ip in ips)
{
if (ip.AddressFamily == AddressFamily.InterNetwork)
{
ret = ip.MapToIPv4().ToString();
}
}
if (ret == "")
{
return null;
}
return ret;
}
}
最后,我们开始服务器的监听。
public void StartRun() {
this.server.Listen(1); //开始监听
while (true) {
Console.WriteLine("wait for client to connect...");
client = this.server.Accept();
break;
}
while (true) {
Console.Write("enter your message>>>");
string message = Console.ReadLine();
client.Send(System.Text.Encoding.Default.GetBytes(message.ToString()));
}
}
这样,一套完整的服务器就构建好了,虽然内容不是非常的完善,但是足够提供我们能力去和Python交流了。
现在我们在主函数中把它实例化。
最后,我们再实现Python客户端的代码即可。
import socket
ip = socket.gethostbyname(socket.gethostname())
port = 45535
server_address_family = (ip,port) #服务器地址族
try:
client = socket.socket()
client.connect(server_address_family)
print("python has already connect to C#")
print("wait message from C#")
while 1:
msg = client.recv(1024)
print(msg.decode())
except Exception as e :
print(e)
print("连接失败...")
完成之后,两者运行的效果可以在下图中看到。实现交流之后,我们就可以定义自己的协议,来规定什么时候传输数据,什么时候传输代码,什么时候传输文件等。如果不懂的问题,可以加我qq529324416,也可以加我的技术讨论群493486382