下面我们来详细看一下程序,我们将逐行的进行分析。
<span style="color:#ff0000;">int simple_server(void)
{
unsigned int plen,dat_p,i1=0,payloadlen=0;
unsigned char i=0,*buf1 = 0;
signed char cmd;
/* 将自己设定的mac,ip,wwwport赋值给系统变量 */
init_ip_arp_udp_tcp(mymac,myip,mywwwport);
printf("\n\r神舟III号MAC地址:0x%x,0x%x,0x%x,0x%x,0x%x,0x%x",mymac[0],mymac[1],mymac[2],mymac[3],mymac[4],mymac[5]);
printf("\n\r IP地址:%d.%d.%d.%d",myip[0],myip[1],myip[2],myip[3]);
printf("\n\r 端口号:%d\n\r\n\r",mywwwport);
while(1)
{
/* 判断是否有接收到有效的包 ,ETH包,不包含校验CRC */
plen = enc28j60PacketReceive(BUFFER_SIZE, buf);
/* 如果收到有效的包,plen将为非0值。*/
if(plen==0)
{
/* 没有收到有效的包就退出重新检测 */
continue;
}
/* 查询ETH包头的类型/长度字节,如果收到目的地址为本机IP的ARP包,则发送一个ARP应答包 */
if(eth_type_is_arp_and_my_ip(buf,plen))
{
/* 如果是返回ARP包 */
make_arp_answer_from_request(buf);
continue;
}
/* 如果接收的目的地址不是本机IP的合法IP包,则重新检测 */
if(eth_type_is_ip_and_my_ip(buf,plen)==0)
{
/* 没有收到有效的包就退出重新检测 */
continue;
}
/* 如果收到ICMP包,并且是ICMP回射请求包 ,则发送一个ICMP回射应答包(判断两个终端之间是否有效连接)*/
if(buf[IP_PROTO_P]==IP_PROTO_ICMP_V && buf[ICMP_TYPE_P]==ICMP_TYPE_ECHOREQUEST_V)
{
printf("\n\r收到主机[%d.%d.%d.%d]发送的ICMP包",buf[ETH_ARP_SRC_IP_P]
,buf[ETH_ARP_SRC_IP_P+1]
,buf[ETH_ARP_SRC_IP_P+2]
,buf[ETH_ARP_SRC_IP_P+3]);
make_echo_reply_from_request(buf, plen);
continue;
}
/*如果收到一个TCP包,并且端口为80,则进行相应处理 */
if (buf[IP_PROTO_P]==IP_PROTO_TCP_V&&buf[TCP_DST_PORT_H_P]==0&&buf[TCP_DST_PORT_L_P]==mywwwport)
{
printf("\n\r神舟III号接收到TCP包,端口为80。");
/*如果这是一个TCP连接请求包,发送一个同步请求应答TCP包 */
if (buf[TCP_FLAGS_P] & TCP_FLAGS_SYN_V)
{
printf("包类型为SYN\n\r");
make_tcp_synack_from_syn(buf);
continue;
}
/*如果这是一个TCP确认包,发送一个同步请求应答TCP包 */
if (buf[TCP_FLAGS_P] & TCP_FLAGS_ACK_V)
{
printf("包类型为ACK\n\r");
/* 初始化数据格式,并获取TCP包,数据区首地址指针 */
init_len_info(buf);
dat_p=get_tcp_data_pointer();
/* 如果这是一个无数据的TCP包 */
if (dat_p==0)
{
/* 如果这是一个要求释放连接(终止)的TCP包 */
if (buf[TCP_FLAGS_P] & TCP_FLAGS_FIN_V)
{
/*发送响应*/
printf("终止连接包\n\r");
make_tcp_ack_from_any(buf);
}
/* 等待重新接收数据包 */
continue;
}
if (strncmp("GET ",(char *)&(buf[dat_p]),4)!=0)
{
/* 如果是Telnet方式登录,返回如下提示信息 */
plen=fill_tcp_data_p(buf,0,PSTR("神舟III号\r\n\n\rHTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n<h1>200 OK</h1>"));
goto SENDTCP;
}
if (strncmp("/ ",(char *)&(buf[dat_p+4]),2)==0)
{
/* 如果是通过网页方式登录,输出如下提示信息 */
plen=fill_tcp_data_p(buf,plen,PSTR("<p>Usage: "));
plen=fill_tcp_data(buf,plen,baseurl);
plen=fill_tcp_data_p(buf,plen,PSTR("password</p>"));
goto SENDTCP;
}
/* 分析网页控制的命令类型 */
cmd=analyse_get_url((char *)&(buf[dat_p+5]));
if (cmd==-1)
{
plen=fill_tcp_data_p(buf,0,PSTR("HTTP/1.0 401 Unauthorized\r\nContent-Type: text/html\r\n\r\n<h1>401 Unauthorized</h1>"));
goto SENDTCP;
}
/* 网页控制点亮LED灯DS1 */
if (cmd==1)
{
LED1_ON();
i=1;
}
/* 网页控制熄灭LED灯DS1 */
if (cmd==0)
{
LED1_OFF();
i=0;
}
/* 更新网页信息 */
plen=print_webpage(buf,(i));
SENDTCP:
/* 发送一个确认TCP包 */
make_tcp_ack_from_any(buf);
/* 发送一个数据TCP包 */
make_tcp_ack_with_data(buf,plen);
continue;
}
}
/* UDP包,监听1200端口的UDP包 */
if (buf[IP_PROTO_P]==IP_PROTO_UDP_V&&buf[UDP_DST_PORT_H_P]==4&&buf[UDP_DST_PORT_L_P]==0xb0)
{
/* 获取UDP包数据区指针首地址 */
payloadlen = buf[UDP_LEN_H_P];
payloadlen = payloadlen<<8;
payloadlen = (payloadlen+buf[UDP_LEN_L_P])-UDP_HEADER_LEN;
/* 将UDP包数据区的数据放到buf1变量中 */
for(i1=0; i1<payloadlen; i1++)
{
buf1[i1]=buf[UDP_DATA_P+i1];
}
/* 回复一个UDP应答包,包的发送的数据内容与接收到的包数据内容相同 */
make_udp_reply_from_request(buf,buf1,payloadlen,myudpport);
}
}
}</span>
|