环境 win7 Anaconda2
一、安装pyserial和modbus-tk:
C:\Users\admin>cd C:\Anaconda2
C:\Anaconda2>easy_install pyserial
Searching for pyserial
Best match: pyserial 3.4
Processing pyserial-3.4-py2.7.egg
pyserial 3.4 is already the active version in easy-install.pth
Installing miniterm.py script to C:\Anaconda2\Scripts
Using c:\anaconda2\lib\site-packages\pyserial-3.4-py2.7.egg
Processing dependencies for pyserial
Finished processing dependencies for pyserial
C:\Anaconda2>python
Python 2.7.12 |Anaconda 4.2.0 (64-bit)| (default, Jun 29 2016, 11:07:13) [MSC v.1500 64 bit (AMD64)] on win32
Type “help”, “copyright”, “credits” or “license” for more information.
Anaconda is brought to you by Continuum Analytics.
Please check out: http://continuum.io/thanks and https://anaconda.org
import serial
C:\Anaconda2>easy_install modbus-tk
Searching for modbus-tk
Reading https://pypi.python.org/simple/modbus-tk/
Downloading https://pypi.python.org/packages/80/71/3d8a6596cd65670d4d2beee262d5964deb933614fd7f58a739d5aa0f0332/modb
us_tk-0.5.7.tar.gz#md5=74c02b9b57dc32913da52d020eaf11d3
Best match: modbus-tk 0.5.7
Processing modbus_tk-0.5.7.tar.gz
Writing c:\users\admin\appdata\local\temp\easy_install-z7i_tm\modbus_tk-0.5.7\setup.cfg
Running modbus_tk-0.5.7\setup.py -q bdist_egg –dist-dir c:\users\admin\appdata\local\temp\easy_install-z7i_tm\modbu
s_tk-0.5.7\egg-dist-tmp-4bmk1v
zip_safe flag not set; analyzing archive contents…
Moving modbus_tk-0.5.7-py2.7.egg to c:\anaconda2\lib\site-packages
Adding modbus-tk 0.5.7 to easy-install.pth file
Installed c:\anaconda2\lib\site-packages\modbus_tk-0.5.7-py2.7.egg
Processing dependencies for modbus-tk
Finished processing dependencies for modbus-tk
C:\Anaconda2>python
Python 2.7.12 |Anaconda 4.2.0 (64-bit)| (default, Jun 29 2016, 11:07:13) [MSC v.1500 64 bit (AMD64)] on win32
Type “help”, “copyright”, “credits” or “license” for more information.
Anaconda is brought to you by Continuum Analytics.
Please check out: http://continuum.io/thanks and https://anaconda.org
import modbus_tk
二、
lwip-win32-msvc-0.1
已经解决的问题:
一:下载lwip的源码,在windows上重新组织文件架构,然后进行编译。刚好美国已经有人做了这样面的工作,所以
就先用一下咯。毕竟一开始要做这方面的工作,还是有难度的。可以下载lwip-win32-msvc-0.1.zip文件。
网络上有很多这样的下载连接,但是都不好用(动不动就要你去注册,花了时间注册好了本以为可以下载了,没想到下载时候提示,积分不够,需要积分可以啊,买卡充值什么的,烦哪。)。官方网也连接不上,后来发现在sina爱问里面的共享里面可以下载,很方便的哦。
下载完了之后解压就可以用了。用vc6打开就可以了。里面有两个工程,一个是Lwip4工程,编译后是lib库,供上层应用程序使用;另一个工程是test,是测试程序。分别编译,lwip4可以顺利的编译通过,但是test工程编译的时候会遇到问题:
(1)找不到packet32.h文件。解决的办法是到官网http://www.winpcap.org/devel.htm上下载winpcap的开发包Download WinPcap 4.0.2 Developer’s Pack,连接是http://www.winpcap.org/install/bin/WpdPack_4_0_2.zip 。下载之后解压即能看到一系列的目录,从include目录下就能找到packet32.h,以及packet32.h文件里include的devioctl.h,一起拷贝过来到工程目录里面。另外还要到Lib文件夹中拷贝packet32.h的实现lib文件packet.lib,然后加到工程中来。问题就迎刃而解了。
(2)typedef struct npf_if_addr {
struct sockaddr_storage IPAddress; ///< IP address.
struct sockaddr_storage SubnetMask; ///< Netmask for that address.
struct sockaddr_storage Broadcast; ///< Broadcast address.
}npf_if_addr;
会报packet32.h中上述结构体中的sockaddr_storage未定义:error C2079: ‘IPAddress’ uses undefined struct ‘sockaddr_storage
解决这个问题,可以自己在packet32.h中定义该结构体:
struct sockaddr_storage {
u_char sa_len;
u_char sa_family;
u_char padding[128];
};
或者sockaddr_storage 改成 sockaddr 也可以解决问题。
(3)pktif.c(191) : error C2065: ‘OID_802_3_PERMANENT_ADDRESS’ : undeclared identifier
pktif.c(199) : error C2065: ‘NDIS_PACKET_TYPE_ALL_LOCAL’ : undeclared identifier
报上述两个错误,是因为这两个变量是在Ntddndis.h文件中定义的,该头文件也是winpcap开发包中的文件,所以如同(1)需要从开发包inlude目录下把该文件拷贝到工程里来,同时在pktif.c文件头加上#include
int socket(int domain, int type, int protocol);
服务器根据地址类型(ipv4,ipv6)、socket类型、协议创建socket。
domain:协议族,常用的有AF_INET、AF_INET6、AF_LOCAL、AF_ROUTE其中AF_INET代表使用ipv4地址
type:socket类型,常用的socket类型有,SOCK_STREAM、SOCK_DGRAM、SOCK_RAW、SOCK_PACKET、SOCK_SEQPACKET等
protocol:协议。常用的协议有,IPPROTO_TCP、IPPTOTO_UDP、IPPROTO_SCTP、IPPROTO_TIPC等
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
把一个地址族中的特定地址赋给socket
sockfd:socket描述字,也就是socket引用
addr:要绑定给sockfd的协议地址
addrlen:地址的长度
通常服务器在启动的时候都会绑定一个地址(如ip地址+端口号),用于提供服务。有些端口号是约定俗成的不能乱用,如80用作http,502用作modbus。
int listen(int sockfd, int backlog);
监听socket
sockfd:要监听的socket描述字
backlog:相应socket可以排队的最大连接个数
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
连接某个socket
sockfd:客户端的socket描述字
addr:服务器的socket地址
addrlen:socket地址的长度
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
TCP服务器监听到客户端请求之后,调用accept()函数取接收请求
sockfd:服务器的socket描述字
addr:客户端的socket地址
addrlen:socket地址的长度
size_t read(int fd, void *buf, size_t count);
读取socket内容
fd:socket描述字
buf:缓冲区
count:缓冲区长度
size_t write(int fd, const void *buf, size_t count);
向socket写入内容,其实就是发送内容
fd:socket描述字
buf:缓冲区
count:缓冲区长度
int close(int fd);
socket标记为以关闭 ,使相应socket描述字的引用计数-1,当引用计数为0的时候,触发TCP客户端向服务器发送终止连接请求。
const unsigned char htmldata[] = “\
\
LWIP\
A WebServer Based on LwIP v1.4.1 Hello world!
/**
* @brief serve tcp connection
* @param conn: connection socket
* @retval None
*/
void http_server(int conn)
{
int buflen = 1500;
int ret;
unsigned char recv_buffer[1500];
/* Read in the request */
ret = read(conn, recv_buffer, buflen);
if(ret <= 0)
{
close(conn);
Printf(“read failed\r\n”);
return;
}
Printf("http server response!\r\n");
if(strncmp((char *)recv_buffer, "GET /lwip", 9) == 0)
{
write(conn, htmldata, sizeof(htmldata)-1);
}
else
{
write(conn, errhtml, sizeof(errhtml)-1);
}
/* Close connection socket */
close(conn);
}
/**
* @brief http_task
* @param arg: pointer on argument(not used here)
* @retval None
*/
static void http_task(void *arg)
{
int sock, newconn, size;
struct sockaddr_in address, remotehost;
/* create a TCP socket */
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
Printf(“can not create socket”);
return;
}
/* bind to port 80 at any interface */
address.sin_family = AF_INET;
address.sin_port = htons(80);
address.sin_addr.s_addr = INADDR_ANY;
if (bind(sock, (struct sockaddr *)&address, sizeof (address)) < 0)
{
Printf(“can not bind socket”);
close(sock);
return;
}
/* listen for connections (TCP listen backlog = 1) */
listen(sock, 1);
size = sizeof(remotehost);
while (1)
{
newconn = accept(sock, (struct sockaddr )&remotehost, (socklen_t )&size);
if (newconn >= 0)
{
http_server(newconn);
}
else
{
close(newconn);
}
}
}
/****************************************************
* void http_task_init(void)
*
* This function initializes the service.
****************************************************/
void http_task_init(void)
{
sys_thread_new( CHARGEN_THREAD_NAME, http_task, 0, 0, TCPIP_THREAD_PRIO+1); //函数栈在移植sys_thread_new中实现
}
/**
* @brief serve modbus_tcp connection
* @param conn: connection socket
* @retval None
*/
void modbus_tcp_server(int conn)
{
int buflen = 1500;
int ret;
unsigned char recv_buffer[1500];
int i;
Printf(“start modbus tcp\r\n”);
ret = read(conn, recv_buffer, buflen);
while ( ret > 0 )
{
ret = read(conn, recv_buffer, buflen);
Printf(“\r\n>:”); // debug print
for(i=0; i