远程WEB控制MP3播放器设计(基于mini2440)

网上有很多 基于mini2440的MP3播放器设计的资料,多是按键控制,这里博主做了些轻微改动,利用远程WEB来控制MP3播放,具体怎么实现,下面会给出,大家先看看效果:

WEB界面:


后台运行:


因为不是什么课程设计报告,博主就不阐述的那么详细,这个设计主要有三部分组成:

1、WEB控制端(就是浏览器);

2、WEB服务器端(将mini2440开发板作为服务器,其中移植了BOA服务器,这里不做详细介绍,大家网上搜一搜,好多资料,BOA服务器是嵌入式设备中用的比较多的WEB服务器);

3、应用程序部分(就是MP3播放器);

下面将代码列出,就其中重要部分进行详解:

MP3播放代码如下:

[cpp] view plaincopy
  1. /* 
  2.  *     SD卡mp3播放器控制程序 
  3.  *     功能: 
  4.              k1:播放、暂停 
  5.              k2:停止播放 
  6.              k3:上一首 
  7.              k4:下一首 
  8.  *     附加:歌曲自动循环播放SD卡/sdcard/song目录中mp3歌曲 
  9.  */  
  10.    
  11. #include <stdio.h>  
  12. #include <stdlib.h>  
  13. #include <unistd.h>  
  14. #include <sys/ioctl.h>  
  15. #include <sys/types.h>  
  16. #include <sys/stat.h>  
  17. #include <fcntl.h>  
  18. #include <signal.h>  
  19. #include <sys/select.h>  
  20. #include <sys/time.h>  
  21. #include <errno.h>  
  22. #include <sys/wait.h>  
  23. #include <string.h>  
  24. #include <sys/ipc.h>  
  25. #include <sys/shm.h>  
  26.   
  27. /*共享内存申请标记*/  
  28. #define PERM S_IRUSR|S_IWUSR                                                      
  29.   
  30. /*双向循环列表:存放歌曲名*/  
  31. struct song               
  32. {  
  33.     char songname[20];  
  34.     struct song *prev;  
  35.     struct song *next;  
  36. };  
  37.   
  38. /*孙子进程id号*/  
  39. pid_t gradchild;  
  40.   
  41. /*子进程id号*/  
  42. pid_t pid;  
  43.   
  44. /*共享内存描述标记*/  
  45. int shmid;  
  46. char *p_addr;  
  47. /*共享内存内容格式*/  
  48. /*|gradchild(孙子进程PID) |+ |空一个字节|+ currentsong(当前播放列表的节点指针)|*/  
  49.   
  50. /*播放标记*/  
  51. int first_key=1;  
  52. int play_flag=0;  
  53.   
  54. /************************************************* 
  55. Function name: play 
  56. Parameter    : struct song * 
  57. Description  : 播放函数 
  58. Return       : void 
  59. Argument     : void 
  60. **************************************************/  
  61. void play(struct song *currentsong)  
  62. {  
  63.     pid_t fd;  
  64.     char *c_addr;  
  65.     char *p;  
  66.     int len;  
  67.     char my_song[30]="/sdcard/song/";   
  68.     while(currentsong)  
  69.     {  
  70.         /*创建子进程,即孙子进程*/  
  71.         fd = fork();  
  72.         if(fd == -1)  
  73.         {     
  74.             perror("fork");  
  75.             exit(1);  
  76.         }  
  77.         else if(fd == 0)   
  78.         {  
  79.             /*把歌曲名加上根路径*/  
  80.             strcat(my_song,currentsong->songname);   
  81.             p = my_song;  
  82.             len = strlen(p);  
  83.             /*去掉文件名最后的'\n'*/  
  84.             my_song[len-1]='\0';  
  85.   
  86.             printf("THIS SONG IS %s\n",my_song);  
  87.                       /*运行madplay播放器,播放MP3*/  
  88.                      system("printf(" THIS SONG IS %s\n", $my_song) >>/tmp/songname");  
  89.           
  90.               
  91.             execl("/bin/madplay","madplay",my_song,NULL);  
  92.             printf("\n\n\n");  
  93.         }  
  94.         else   
  95.         {  
  96.             /*内存映射*/  
  97.               
  98.             c_addr = shmat(shmid,0,0);  
  99.   
  100.               
  101.             memcpy(c_addr,&fd,sizeof(pid_t));  
  102.             memcpy(c_addr + sizeof(pid_t)+1,¤tsong,4);  
  103.   
  104.             /*使用wait阻塞子进程,直到孙子进程播放完才能被唤醒; 
  105.               当被唤醒时,表示播放MP3期间没有按键按下,则继续顺序播放下一首MP3*/  
  106.               
  107.             if(fd == wait(NULL))  
  108.             {  
  109.                 currentsong = currentsong->next;  
  110.                 printf("THE NEXT SONG IS %s\n",currentsong->songname);  
  111.             }  
  112.         }  
  113.     }  
  114. }  
  115.   
  116. /************************************************* 
  117. Function name: creat_song_list 
  118. Parameter    : void 
  119. Description  : 创建歌曲名的双向循环链表 
  120. Return       : struct song * 
  121. Argument     : void 
  122. **************************************************/  
  123. struct song *creat_song_list(void)  
  124. {     
  125.     FILE *fd;  
  126.     size_t size;  
  127.     size_t len;  
  128.     char *line = NULL;  
  129.     struct song *head;  
  130.     struct song *p1;  
  131.     struct song *p2;  
  132.     system("ls /sdcard/song >song_list");  
  133.     fd = fopen("song_list","r");  
  134.   
  135.     p1 = (struct song *)malloc(sizeof(struct song));  
  136.   
  137.     printf("==================================song list=====================================\n");  
  138.     system("ls /sdcard/song");    
  139.     printf("\n");  
  140.     printf("================================================================================\n");  
  141.     size = getline(&line,&len,fd);  
  142.   
  143.     strncpy(p1->songname,line,strlen(line));  
  144.     head = p1;  
  145.     while((size = getline(&line,&len,fd)) != -1) //从文件中读取一行,直到出错或者到文件尾EOF返回-1  
  146.     {     
  147.         p2 = p1;  
  148.         p1 = (struct song *)malloc(sizeof(struct song));  
  149.         strncpy(p1->songname,line,strlen(line));  
  150.         p2->next = p1;  
  151.         p1->prev = p2;     
  152.     }  
  153.     //此时到了文件尾,若是循环列表,则下一首为head,即第一首   
  154.     p1->next = head;  
  155.     head->prev = p1;  
  156.     p1 = NULL;  
  157.     p2 = NULL;  
  158.     system("rm -rf song_list");  
  159.     return head;  
  160. }  
  161. /************************************************* 
  162. Function name: startplay 
  163. Parameter    : pid_t *,struct song * 
  164. Description  : 开始播放函数 
  165. Return       : void 
  166. Argument     : void 
  167. **************************************************/  
  168. void startplay(pid_t *childpid,struct song *my_song)  
  169. {  
  170.     pid_t pid;  
  171.     int ret;  
  172.     /*创建子进程*/  
  173.     pid = fork();  
  174.   
  175.     if(pid > 0) //父进程  
  176.     {  
  177.         *childpid = pid; //子进程PID初始化  
  178.         play_flag = 1;  
  179.         sleep(1);  
  180.         /*读取共享内存保存的pid,初始化孙子进程的pid*/  
  181.         memcpy(&gradchild,p_addr,sizeof(pid_t));  
  182.           
  183.     }  
  184.     else if(0 == pid) //子进程  
  185.     {     
  186.         /*子进程播放MP3函数*/  
  187.         play(my_song);  
  188.     }  
  189. }  
  190. /************************************************* 
  191. Function name: my_pause 
  192. Parameter    : pid_t 
  193. Description  : 暂停函数 
  194. Return       : void 
  195. Argument     : void 
  196. **************************************************/  
  197. void my_pause(pid_t pid)  
  198. {  
  199.     printf("=======================PAUSE!PRESS K1 TO CONTINUE===================\n");  
  200.     kill(pid,SIGSTOP); //对孙子进程发送SIGSTOP信号  
  201.     play_flag = 0;  
  202. }  
  203.   
  204. /************************************************* 
  205. Function name: my_pause 
  206. Parameter    : pid_t 
  207. Description  : 停止播放函数 
  208. Return       : void 
  209. Argument     : void 
  210. Autor & date : Hanson  11,04, 05 
  211. **************************************************/  
  212. void my_stop(pid_t g_pid)  
  213. {  
  214.   
  215.     printf("=======================STOP!PRESS K1 TO START PLAY===================\n");  
  216.     kill(g_pid,SIGKILL); //对孙子进程发送SIGKILL信号  
  217.     kill(pid,SIGKILL);   //对子进程发送SIGKILL信号  
  218.     first_key=1;  
  219.   
  220. }  
  221.   
  222. /************************************************* 
  223. Function name: conti_play 
  224. Parameter    : pid_t 
  225. Description  : 继续函数 
  226. Return       : void 
  227. Argument     : void 
  228. **************************************************/  
  229. void conti_play(pid_t pid)  
  230. {  
  231.     printf("===============================CONTINUE=============================\n");  
  232.     kill(pid,SIGCONT); //对孙子进程发送SIGCONT信号  
  233.     play_flag=1;  
  234. }  
  235.   
  236. /************************************************* 
  237. Function name: next 
  238. Parameter    : pid_t 
  239. Description  : 下一首函数 
  240. Return       : void 
  241. Argument     : void 
  242. **************************************************/  
  243. void next(pid_t next_pid)  
  244. {  
  245.     struct song *nextsong;  
  246.   
  247.     printf("===============================NEXT MP3=============================\n");  
  248.     /*从共享内存获得孙子进程播放歌曲的节点指针*/  
  249.     memcpy(&nextsong,p_addr + sizeof(pid_t)+1,4);  
  250.     /*指向下首歌曲的节点*/  
  251.     nextsong = nextsong->next;  
  252.     /*杀死当前歌曲播放的子进程,孙子进程*/  
  253.     kill(pid,SIGKILL);  
  254.     kill(next_pid,SIGKILL);  
  255.     wait(NULL);  
  256.     startplay(&pid,nextsong);  
  257. }  
  258.   
  259. /************************************************* 
  260. Function name: prev 
  261. Parameter    : pid_t 
  262. Description  : 上一首函数 
  263. Return       : void 
  264. Argument     : void 
  265. **************************************************/  
  266. void prev(pid_t prev_pid)  
  267. {  
  268.     struct song *prevsong;  
  269.     /*从共享内存获得孙子进程播放歌曲的节点指针*/  
  270.     printf("===============================PRIOR MP3=============================\n");  
  271.     memcpy(&prevsong,p_addr + sizeof(pid_t)+1,4);  
  272.     /*指向上首歌曲的节点*/  
  273.     prevsong = prevsong->prev;  
  274.     /*杀死当前歌曲播放的子进程,孙子进程*/  
  275.     kill(pid,SIGKILL);  
  276.     kill(prev_pid,SIGKILL);  
  277.     wait(NULL);  
  278.     startplay(&pid,prevsong);  
  279. }  
  280.   
  281. /************************************************* 
  282. Function name: main 
  283. Parameter    : void 
  284. Description  : 主函数 
  285. Return       : int 
  286. Argument     : void 
  287. **************************************************/  
  288. int main(void)  
  289. {  
  290. //  int buttons_fd;  
  291.     int mp3_control_pipe;  
  292.     int mp3_control_pipe_write;  
  293. //  int key_value;  
  294.     int playnum;  
  295. //  char playnum;  
  296.     struct song *head;  
  297.     /*打开设备文件*/  
  298. //  buttons_fd = open("/dev/key", 0);  
  299. //  if (buttons_fd < 0) {  
  300. //      perror("open device buttons");  
  301. //      exit(1);  
  302. //  }  
  303.   
  304.    /*创建命名管道mp3-control*/  
  305.     unlink("/tmp/mp3_control");  
  306.     mkfifo("/tmp/mp3_control",0666);  
  307.       
  308.     mp3_control_pipe=open("/tmp/mp3_control",O_RDONLY|O_NONBLOCK);  
  309.     mp3_control_pipe_write=open("/tmp/mp3_control",O_WRONLY|O_NONBLOCK);  
  310.   
  311.   
  312.     if(mp3_control_pipe<0)  
  313.     {  
  314.        perror("open control pipe for read");    
  315.         }  
  316.   
  317.     printf("**********基于mini2440的网页控制MP3播放器*********** \n");  
  318.     printf("********************XXX制作 ************************ \n");  
  319.     printf("**************嵌入式开发项目************************ \n");  
  320.       
  321.   /*创建播放列表*/  
  322.     head = creat_song_list();  
  323.       
  324.     printf("===================================FUNTION======================================\n\n");  
  325.     printf("        K1:播放、暂停     K2:停止播放   K3:下一歌曲      K4:上一歌曲  \n\n");  
  326.     printf("================================================================================\n");  
  327.   
  328.   
  329.   /*共享内存:用于存放子进程ID,播放列表位置*/  
  330.     if((shmid = shmget(IPC_PRIVATE,5,PERM))== -1)  
  331.         exit(1);  
  332.     p_addr = shmat(shmid,0,0);  
  333.     memset(p_addr,'\0',1024);  
  334.       
  335.       
  336.     while(1)   
  337.     {  
  338.         fd_set rds;/*先声明一个 fd_set 集合来保存我们要检测的 buttons_fd句柄*/  
  339.         int ret1;  
  340.   
  341.         FD_ZERO(&rds);/*用select函数之前将rds清零*/  
  342.         FD_SET(mp3_control_pipe, &rds);/*将检测到的句柄放到集合rds里*/  
  343.   
  344.         /*监听获取键值*/  
  345.         //struct timeval timeout = {30,0};  
  346.         ret1 = select(mp3_control_pipe + 1, &rds, NULL, NULL,NULL);  
  347.         //printf ("%s %d %d\n", __FUNCTION__, __LINE__, ret1);  
  348.         if (ret1 < 0)   
  349.         {  
  350.             perror("select");  
  351.             exit(1);  
  352.         }  
  353.         if (ret1 == 0)   
  354.             printf("Timeout.\n");  
  355.         else if (FD_ISSET(mp3_control_pipe, &rds))  
  356.         {  
  357.             static char buffer[10];  
  358.             int ret = read(mp3_control_pipe, &buffer, 2);  
  359. //          printf ("%s %d %d\n", __FUNCTION__, __LINE__, ret);  
  360.             if (ret != 2)   
  361.             {  
  362.                 if (errno != EAGAIN) {  
  363.                     perror("read buttons\n");  
  364.                     continue;  
  365.                 }  
  366.             }   
  367.             else  
  368.             {     
  369.                 int playnum1;  
  370.                 if(sscanf(buffer,"%d",&playnum1)==1)  
  371.                     {  
  372.                      playnum=playnum1;  
  373.                     }  
  374.                 memset(buffer,0,sizeof(buffer));  
  375.   
  376.                 printf("buttons_value: %d\n", playnum);  
  377.                   
  378.                 /*首次播放,必须是按键1*/  
  379.                 if(first_key){  
  380.                     switch(playnum)  
  381.                     {     
  382.                     case 0:  
  383.                         startplay(&pid,head);  
  384.                         first_key=0;  
  385.                         break;  
  386.                     case 1:  
  387.                     case 2:  
  388.                     case 3:  
  389.                         printf("=======================PRESS K1 TO START PLAY===================\n");  
  390.                         break;  
  391.                     default:  
  392.                         printf("=======================PRESS K1 TO START PLAY===================\n");  
  393.                         break;  
  394.                     } //end switch  
  395.                 }//end if(first_key)  
  396.                 /*若不是首次播放,则根据不同键值处理*/  
  397.                 else if(!first_key){  
  398.                     switch(playnum)  
  399.                     {  
  400.                     case 0:  
  401.                         //printf("play_flag:%d\n",play_flag);  
  402.                         if(play_flag)  
  403.                             my_pause(gradchild);  
  404.                         else  
  405.                             conti_play(gradchild);  
  406.                         break;  
  407.                     case 1:  
  408.                         my_stop(gradchild);  
  409.                         break;  
  410.                     case 2:  
  411.                         next(gradchild);  
  412.                         break;  
  413.                     case 3:  
  414.                         prev(gradchild);  
  415.                         break;  
  416.                     } //end switch  
  417.              }//end if(!first_key)  
  418.   
  419.             }  
  420.                   
  421.         }  
  422.     }  
  423.     close(mp3_control_pipe);  
  424.     return 0;  
  425. }  


MP3播放的实现答题架构没有变,主要修改部分是控制部分,原来控制是由按键中断来实现的,现将其改为由进程间通信—— 命名管道 来控制,现将主要部分代码列出:

[cpp] view plaincopy
  1. int main(void)  
  2. {  
  3.   
  4.     int mp3_control_pipe;  
  5.     int mp3_control_pipe_write;  
  6.     int playnum;  
  7.     struct song *head;  
  8.     /*打开设备文件*/  
  9.   
  10.     *创建命名管道mp3-control*/  
  11.     unlink("/tmp/mp3_control");  
  12.     mkfifo("/tmp/mp3_control",0666);  
  13.       
  14.     mp3_control_pipe=open("/tmp/mp3_control",O_RDONLY|O_NONBLOCK);  
  15.     mp3_control_pipe_write=open("/tmp/mp3_control",O_WRONLY|O_NONBLOCK);  
  16.   
  17.   
  18.     if(mp3_control_pipe<0)  
  19.     {  
  20.             perror("open control pipe for read");    
  21.     }  
这部分主要是建立一个命名管道mp3_control,以实现进程间通信,原来博主只是为了在MP3模块中不断的读取管道里面的数据,所以第一次时只是单独的读:

[cpp] view plaincopy
  1. mp3_control_pipe=open("/tmp/mp3_control",O_RDONLY|O_NONBLOCK);  
但是后面执行时,却一直读取管道里面的内容,就是对一个相同的数据不断地读取,成了一个死循环,最后查找资料把写管道也打开了,这样才OK了,大家知道是什么原因吗?博主查找了相关资料,却没找到答案,只在某地看到这个,大家看看是什么意思,为什么要把读和写都打开


下面这段代码是不断的监听管道里面的数值,并作出相应操作

[cpp] view plaincopy
  1.  /*共享内存:用于存放子进程ID,播放列表位置*/  
  2.     if((shmid = shmget(IPC_PRIVATE,5,PERM))== -1)  
  3.         exit(1);  
  4.     p_addr = shmat(shmid,0,0);  
  5.     memset(p_addr,'\0',1024);  
  6.       
  7.       
  8.     while(1)   
  9.     {  
  10.         fd_set rds;/*先声明一个 fd_set 集合来保存我们要检测的 buttons_fd句柄*/  
  11.         int ret1;  
  12.   
  13.         FD_ZERO(&rds);/*用select函数之前将rds清零*/  
  14.         FD_SET(mp3_control_pipe, &rds);/*将检测到的句柄放到集合rds里*/  
  15.   
  16.         /*监听获取键值*/  
  17.         //struct timeval timeout = {30,0};  
  18.         ret1 = select(mp3_control_pipe + 1, &rds, NULL, NULL,NULL);  
  19.         //printf ("%s %d %d\n", __FUNCTION__, __LINE__, ret1);  
  20.         if (ret1 < 0)   
  21.         {  
  22.             perror("select");  
  23.             exit(1);  
  24.         }  
  25.         if (ret1 == 0)   
  26.             printf("Timeout.\n");  
  27.         else if (FD_ISSET(mp3_control_pipe, &rds))  
  28.         {  
  29.             static char buffer[10];  
  30.             int ret = read(mp3_control_pipe, &buffer, 2);  
  31. //          printf ("%s %d %d\n", __FUNCTION__, __LINE__, ret);  
  32.             if (ret != 2)   
  33.             {  
  34.                 if (errno != EAGAIN) {  
  35.                     perror("read buttons\n");  
  36.                     continue;  
  37.                 }  
  38.             }   
  39.             else  
  40.             {     
  41.                 int playnum1;  
  42.                 if(sscanf(buffer,"%d",&playnum1)==1)  
  43.                     {  
  44.                      playnum=playnum1;  
  45.                     }  
  46.                 memset(buffer,0,sizeof(buffer));  
  47.   
  48.                 printf("buttons_value: %d\n", playnum);  

二、BOA服务器

BOA服务器这里先不详细介绍,主要通过调用CGI程序实现与应用程序的信息交互,这里就是调用CGI程序向管道里写数据的,代码如下:

[cpp] view plaincopy
  1. #!/bin/sh  
  2.   
  3. type=0  
  4.   
  5.   
  6. case $QUERY_STRING in  
  7.     *play*)  
  8.         type=0  
  9.         ;;  
  10.     *stop*)  
  11.         type=1  
  12.         ;;  
  13.     *priv*)  
  14.         type=2  
  15.         ;;  
  16.     *next*)  
  17.         type=3  
  18.         ;;  
  19. esac  
  20.   
  21.   
  22.   
  23. /bin/echo $type > /tmp/mp3_control  
  24.   
  25. echo "Content-type: text/html; charset=gb2312"  
  26. echo  
  27. /bin/cat mp3-result.template  
  28.   
  29. exit 0  


这里是用shell脚本编写的,当然也可以用C来编写,具体BOA服务器和CGI博主打算单独写在一篇文章里。


三、WEB控制部分

  博主对WEB开发没有学习过,只是利用别人的脚本进行简单更改,代码如下:

[cpp] view plaincopy
  1. <html xmlns="http://www.w3.org/1999/xhtml">  
  2. <head>  
  3. <meta http-equiv="Content-Type" content="text/html; charset=gb2312" />  
  4. <title>网页控制MP3</title>  
  5. <style type="text/css">  
  6. <!--  
  7. a:link {  color:#FFFFFF; text-decoration: none }  
  8. a:visited { color:#FFFFFF; text-decoration: none}  
  9. a:hover {  color: #FF6600; text-decoration: underline}  
  10. a.develop_item_link:link {color:#FF6600; font-size: 9pt; text-decoration:underline}  
  11. a.left_item_style:hover {color:green; font-size: 9pt; text-decoration:none}  
  12. a.develop_item_style:hover {color:"#00FF00"; font-size: 9pt; text-decoration:none}  
  13. a.download_item_style:hover {color:bule; font-size: 9pt; text-decoration:none}  
  14. a.middle_item_style:hover {color:red; font-size: 12pt; text-decoration:underline}  
  15. a.middle_item_style:link {  color: #000000; text-decoration: none}  
  16. a.middle_item_style:visited { color:#000000; text-decoration: none}  
  17. .STYLE13 {color:#FFFFFF; text-decoration: none}  
  18. .STYLE14 {  
  19.     font-size: 16px;  
  20.     font-weight: bold;  
  21. }  
  22.   
  23. -->  
  24. </style>  
  25.   
  26. <script language="JavaScript">  
  27. <!--  
  28.   
  29. var j,old_image;  
  30. function change_over(){  
  31.   var ob=change_over.arguments;  
  32.   for(i=0;i<document.all.length;i++)  
  33.   if(document.all[i].name==ob[0]) j=i;  
  34.   old_image=document.all[j].src;  
  35.   document.all[j].src=ob[1];  
  36. }   
  37.   
  38. function change_out(){  
  39.   document.all[j].src=old_image;  
  40. }  
  41. //-->  
  42. </script>  
  43. </head>  
  44.   
  45. <body bgcolor="#666666">  
  46. <table width="800" align="center" cellpadding="0">  
  47. <tr>  
  48.   <td width="9"> </td>  
  49.   <td width="781" colspan="2"><div align="center"><img src="images1/bar.jpg" width="780" height="120" /></div></td>  
  50. </tr>  
  51. <tr>  
  52.   <td> </td>  
  53.   <td colspan="2"><table width="780" cellpadding="0" cellspacing="0" border="0">  
  54.     <tr>  
  55.       <td> </td>  
  56.       <td> </td>  
  57.       <td> </td>  
  58.     </tr>  
  59.     <tr>  
  60.       <td width="250"><a href="mp3_control.html" onMouseOut="change_out()" onMouseOver="change_over('Image1','images1/bar_left_thick.jpg')"><img src="images1/bar_left_thick.jpg" width="780" height="37" border="0" name="Image1"></a></td>  
  61.         
  62.     </tr>  
  63.   </table></td>  
  64. </tr>  
  65. <tr>  
  66.   <td> </td>  
  67.   <td colspan="2"> </td>  
  68. </tr>  
  69. <tr>  
  70.   <td> </td>  
  71.   <td colspan="2"><form method="get" action="mp3_control.cgi" name="WEBCAM-TEST">  
  72.     <div align="center"><span class="STYLE9">点击下面的MP3播放选项,可以选择MP3播放 </span>  
  73.       </div>  
  74.   </form></td>  
  75. </tr>  
  76.   
  77.   
  78. <tr>  
  79.   <td> </td>  
  80.   <td colspan="2" align="center"><form method="get" action="mp3_control.cgi" name="LED-TEST">  
  81.   
  82.        <div align="left">  
  83.       <table border="0" width="280" align="center">  
  84.         <tr>  
  85.           <td width="133">  
  86.             <p align="center">选择播放</td>  
  87.              
  88.           </tr>  
  89.         <tr>  
  90.        </tr>  
  91.         <tr>  
  92.           <td width="140">  
  93.             <p align="center">  <input type="radio" value="play" checked name="type">播放/暂停</td>  
  94.             </tr>  
  95.             <tr>  
  96.                <td width="140">  
  97.                  <p align="center"><input type="radio" name="type" value="stop" checked>停止播放</td>  
  98.                  </tr>  
  99.                  <tr>       
  100.                      <td width="140">  
  101.                      <p align="center"> <input type="radio" name="type" value="priv">上一歌曲</td>  
  102.                      </tr>  
  103.                      <tr>  
  104.                          <td width="140">  
  105.                          <p align="center"><input type="radio" name="type" value="next">下一歌曲</td>  
  106.          
  107.             </tr>  
  108.   
  109.         <tr>  
  110.           <td colspan="2" width="272">  
  111.             <p align="center"><input type="submit" value="确定(OK)" name="submit"></td>  
  112.         </tr>  
  113.       </table>  
  114.      </div>  
  115.     <div align="center"></div><div align="center"></div><div align="left"></div><div align="left"></div></form> </td>  
  116. </tr>  
  117. <tr>  
  118.   <td height="42"> </td>  
  119.   <td colspan="2" background="images1/bottom.jpg" height="39" >  
  120.     <div align="center" class="STYLE13"> <strong>Web Server test page 肖志强制作</strong> <a href="http://embedclub.taobao.com/" class="STYLE14">17768137013 </a></div></td>  
  121. </tr>  
  122. <tr>  
  123.   <td> </td>  
  124.   <td colspan="2" align="center"> </td>  
  125. </tr>  
  126. </table>  
  127. </body>  
  128. </html>  

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/402033.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

嵌入式数据库 SQLite 浅析

SQLite是一个非常轻量级自包含(lightweight and self-contained)的DBMS&#xff0c;它可移植性好&#xff0c;很容易使用&#xff0c;很小&#xff0c;高效而且可靠。SQLite嵌入到使用它的应用程序中&#xff0c;它们共用相同的进程空间&#xff0c;而不是单独的一个进程。从外…

socket 请求Web服务器过程

HTTP协议只是一个应用层协议&#xff0c;它底层是通过TCP进行传输数据的。因此&#xff0c;浏览器访问Web服务器的过程必须先有“连接建立”的发生。 而有人或许会问&#xff1a;众所周知&#xff0c;HTTP协议有两大特性&#xff0c;一个是“无连接”性&#xff0c;一个是“无状…

有些事情现在不做一辈子就都不会做了

这句话最近一直印在我的脑海里。这句话最早是在Casperkid的百度空间里面看见的&#xff0c;那时他生日。作为师傅的刺&#xff08;道哥&#xff09;送了他自己写的一本《白帽子讲WEB安全》给他&#xff0c;并在扉页上写着这句话。那时一看到这句话&#xff0c;仿佛有种触电的感…

HTTP 数据包头解析

一、连接至Web服务器 一个客户端应用&#xff08;如Web浏览器&#xff09;打开到Web服务器的HTTP端口的一个套接字&#xff08;缺省为80&#xff09;。 例如&#xff1a;http://www.myweb.com:8080/index.html 在Java中&#xff0c;这将等同于代码&#xff1a; [java] view pla…

Shell 脚本中如何使用make命令

最近开发的项目中需要编写Shell脚本对整个工程进行自动化编译&#xff0c;即在Shell脚本中使用make命令来进行编译&#xff0c;下面回顾一下Shell脚本中如何使用make命令&#xff09; 在开发一个系统时&#xff0c;一般是将一个系统分成几个模块&#xff0c;这样做提高了系统的…

Shell 脚本知识回顾 (六) —— Shell 函数

一、Shell函数&#xff1a;Shell函数返回值、删除函数、在终端调用函数 函数可以让我们将一个复杂功能划分成若干模块&#xff0c;让程序结构更加清晰&#xff0c;代码重复利用率更高。像其他编程语言一样&#xff0c;Shell 也支持函数。Shell 函数必须先定义后使用。 Shell 函…

Shell 脚本知识回顾 (五) —— Shell 循环

一、Shell for循环 与其他编程语言类似&#xff0c;Shell支持for循环。 for循环一般格式为&#xff1a;for 变量 in 列表 docommand1command2...commandN done 列表是一组值&#xff08;数字、字符串等&#xff09;组成的序列&#xff0c;每个值通过空格分隔。每循环一次&…

Shell 脚本知识回顾 (四) —— Shell 命令及Shell 相关语句

一、Shell echo命令 echo是Shell的一个内部指令&#xff0c;用于在屏幕上打印出指定的字符串。命令格式&#xff1a;echo arg您可以使用echo实现更复杂的输出格式控制。 显示转义字符 echo "\"It is a test\""结果将是&#xff1a;"It is a test"…

Shell 脚本知识回顾 (三) —— 替换、运算符、字符串、数组

一、Shell替换&#xff1a;Shell变量替换&#xff0c;命令替换&#xff0c;转义字符 如果表达式中包含特殊字符&#xff0c;Shell 将会进行替换。例如&#xff0c;在双引号中使用变量就是一种替换&#xff0c;转义字符也是一种替换。 举个例子&#xff1a; [cpp] view plaincop…

Shell 脚本知识回顾 (二) —— Shell变量

一、Shell变量&#xff1a;Shell变量的定义、删除变量、只读变量、变量类型 Shell支持自定义变量。定义变量 定义变量时&#xff0c;变量名不加美元符号&#xff08;$&#xff09;&#xff0c;如&#xff1a; [cpp] view plaincopy variableName"value" 注意&…

Shell 脚本知识回顾 (一) —— 基础篇

一、Shell简介&#xff1a;什么是Shell&#xff0c;Shell命令的两种执行方式 Shell本身是一个用C语言编写的程序&#xff0c;它是用户使用Unix/Linux的桥梁&#xff0c;用户的大部分工作都是通过Shell完成的。Shell既是一种命令语言&#xff0c;又是一种程序设计语言。作为命令…

红帽集群RHCS

1、简介&#xff1a;RHCS是RedHatClusterSuite的缩写&#xff0c;也就是红帽子集群套件&#xff0c;RHCS是一个能够提供高可用性、高可靠性、负载均衡、存储共享且经济廉价的集群工具集合&#xff0c;它将集群系统中三大集群架构融合一体&#xff0c;可以给web应用、数据库应用…

Java 基础——数组解析

数组对于每一门编辑应语言来说都是重要的数据结构之一&#xff0c;当然不同语言对数组的实现及处理也不尽相同。 Java语言中提供的数组是用来存储固定大小的同类型元素。 可以声明一个数组变量&#xff0c;如numbers[100]来代替直接声明100个独立变量number0&#xff0c;number…

《在你身边,为你设计》-哪位知道下载、在线阅读地址啊?

《在你身边&#xff0c;为你设计》-前端UI必读出自腾讯CDChttp://cdc.tencent.com/?p6761今天听同事说这本书写的非常好&#xff0c;改变了他关于前端UI的许多看法&#xff0c;可谓&#xff1a;醍醐灌顶。可惜我网上找了下都需要Money买&#xff0c;哪位有在线阅读、PDF下载地…

一、OpenStack架构

DashBoardHorizon提供WEB界面ComputerNova计算也就是虚拟机NetworkingNeutron提供给nova网络支持Object StorageSwift提供对象存储Block StorageCinder提供云硬盘给nova&#xff0c;同时备份到SwiftIdentity SserviceKeystone提供所有组件的认证Image ServiceGlance提供给nova镜…

Java 三大特性 —— 多态

Java中多态性的实现 一、什么是多态 1.面向对象的三大特性&#xff1a;封装、继承、多态。从一定角度来看&#xff0c;封装和继承几乎都是为多态而准备的。这是我们最后一个概念&#xff0c;也是最重要的知识点。 2.多态的定义&#xff1a;指允许不同类的对象对同一消息做出响应…

linux /proc/cpuinfo文件分析

为什么80%的码农都做不了架构师&#xff1f;>>> 基于不同指令集&#xff08;ISA&#xff09;的CPU产生的/proc/cpuinfo文件不一样&#xff0c;基于X86指令集CPU的/proc/cpuinfo文件包含如下内容&#xff1a; processor  &#xff1a; 0vendor_id  &#xff1a;…

Java 高级类(下) —— 内部类和匿名类

Java内部类&#xff08;Inner Class&#xff09;&#xff0c;类似的概念在C里也有&#xff0c;那就是嵌套类&#xff08;Nested Class&#xff09;&#xff0c;乍看上去内部类似乎有些多余&#xff0c;它的用处对于初学者来说可能并不是那么显著&#xff0c;但是随着对它的深入…

Java 高级类(上) —— 抽象类和接口

在面向对象的概念中&#xff0c;我们知道所有的对象都是通过类来描绘的&#xff0c;但是并不是所有的类都是用来描绘对象的&#xff0c;如果一个类中没有包含足够的信息来描绘一个具体的对象&#xff0c;这样的类就是抽象类。 抽象类往往用来表征我们在对问题领域进行分析、 设…

【Git入门之五】版本管理

2019独角兽企业重金招聘Python工程师标准>>> 1.版本回退 我们先看一下从项目开始到现在做了什么操作。 [cpp] view plaincopy #总共是4个操作 $ git log --prettyoneline c5c83cfcdb25c67a5c66b4fe3844d0ea912830ec remove JackyData03 a25c58804cb3f4045564fc0e…