TCP/IP协议的编写

来源:互联网 发布:cf手雷伤害数据 编辑:程序博客网 时间:2024/05/08 03:59
 

新一篇: VC的一些小技巧 | 

基于HHARM9-EDU的TCP/IP(UDP)协议的实现
 
 
摘 要:嵌入式技术的发展日新月异,现如今,嵌入式设备已经广泛应用于各种网络,本文简要地说明一下如何实现PCHHARM9-EDU之间的TCP/IP(UDP) 通讯。
关键词嵌入式系统 TCP/IP协议  协议端口  套接字 UDP协议
 
ABSTRACTThe development ofembedded system make good time, now the devices of embedded system have largely applied to many kinds of network. I will briefly account for how to achieve the communication between PC and HHARM9-EDU in this article.
KEYWORDSembedded system   TCP/IP   protocol port   socket   UDP
 
一、TCP/IP协议的概念:
传统的开放式系统互连参考模型,是一种通信协议的7层抽象的参考模型,其中每一层执行某一特定任务。该模型的目的是使各种硬件在相同的层次上相互通信。这7层是:物理层、数据链路层、网路层、传输层、话路层、表示层和应用层。
TCP/IP起源于美国国防部高级研究规划署(DARPA)的一项研究计划——实现若干台主机的相互通信。现在TCP/IP已成为Internet上通信的工业标准。
TCP/IP通讯协议采用了4层的层级结构,每一层都呼叫它的下一层所提供的网络来完成自己的需求。这4层分别为:
应用层:应用程序间沟通的层,如简单电子邮件传输(SMTP)、文件传输协议(FTP)、网络远程访问协议(Telnet)等。
传输层:在此层中,它提供了节点间的数据传送服务,如传输控制协议(TCP)、用户数据报协议(UDP)等,TCPUDP给数据包加入传输数据并把它传输到下一层中,这一层负责传送数据,并且确定数据已被送达并接收。
网络层:负责提供基本的数据封包传送功能,让每一块数据包都能够到达目的主机(但不检查是否被正确接收),如网际协议(IP)。
网络接口:对实际的网络媒体的管理,定义如何使用实际网络(如EthernetSerial Line等)来传送数据。
TCP/IPOSI参考模型的对应关系如下:
 
 
二、网络传输中一个重要概念――端口:
按照OSI七层模型的描述,传输层提供进程(应用程序)通信的能力。为了标识通信实体中进行通信的进程(应用程序),TCP/IP协议提出了协议端口(protocol port,简称端口)的概念。
端口是一种抽象的软件结构(包括一些数据结构和I/O缓冲区)。应用程序通过系统调用与某端口建立连接(binding)后,传输层传给该端口的数据都被相应的进程所接收,相应进程发给传输层的数据都通过该端口输出。
端口用一个整数型标识符来表示,即端口号。端口号跟协议相关,TCP/IP传输层的两个协议TCP和UDP是完全独立的两个软件模块,因此各自的端口号也相互独立。
端口使用一个16位的数字来表示,它的范围是0~65535,1024以下的端口号保留给预定义的服务。例如:http使用80端口。
 
 
三、套接字(socket)的引入:
为了能够方便的开发网络应用软件,由美国伯克利大学在Unix上推出了一种应用程序访问通信协议的操作系统调用socket(套接字)。socket的出现,使程序员可以很方便地访问TCP/IP,从而开发各种网络应用的程序。
随着Unix的应用推广,套接字在编写网络软件中得到了极大的普及。后来,套接字又被引进了Windows等操作系统,成为开发网络应用程序的非常有效快捷的工具。
套接字存在于通信区域中。通信区域也叫地址族,它是一个抽象的概念,主要用于将通过套接字通信的进程的共有特性综合在一起。套接字通常只与同一区域的套接字交换数据(也有可能跨区域通信,但这只在执行了某种转换进程后才能实现)。Windows Sockets只支持一个通信区域:网际域( AF_INET),这个域被使用网际协议簇通信的进程使用。
 
 
四、UDP协议:
UDP是一个无连接协议,传输数据之前源端和终端不建立连接,当它想传送时就简单地去抓取来自应用程序的数据,并尽可能快地把它扔到网络上。在发送端,UDP传送数据的速度仅仅是受应用程序生成数据的速度、计算机的能力和传输带宽的限制;在接收端,UDP把每个消息段放在队列中,应用程序每次从队列中读一个消息段。
基于UDP(面向无连接)的socket编程:
⑴服务器端(接收端)程序:
1、创建套接字(socket)。   
2、将套接字绑定到一个本地地址和端口上(bind)。
3、等待接收数据(recvfrom)。
4、关闭套接字。
 
⑵客户端(发送端)程序:
1、创建套接字(socket)。   
2、向服务器发送数据(sendto)。
3、关闭套接字。
 
 
五、编程实现如下:
一共有两个程序:服务器端(接收端)程序和客户器端(发送端)程序
服务器端程序运行在实验箱上,客户端程序运行在PC上,从客户端发送消息,服务端收到消息显示在触摸屏上,并回复一条消息给客户端。
下面分别说明:
⑴服务器端(接收端)程序:
服务器端程序运行在实验箱上。
首先在PC上调试,操作系统是RedHat 9,调试工具为MINIGUI V1.3.3,MINIGUI上调试完成后,交叉编译后在实验箱上成功运行,效果图如下:
附:关键源代码
case MSG_TIMER:
        sin_size=sizeof(struct sockaddr_in);
        num = recvfrom(sockfd,msg,MAXDATASIZE,0,
            (struct sockaddr *)&client,&sin_size);                                   
 
        if (num < 0){
        perror("recvfrom error/n");
        exit(1);
        }
 
        msg[num] = '/0';
        printf("You got a message (%s) from %s/n",
            msg,inet_ntoa(client.sin_addr) );
        SetWindowText (GetDlgItem (hDlg, IDC_static), msg);
        sprintf(tempBuf,"Welcome %s to my server.",
            inet_ntoa(client.sin_addr));
        sendto(sockfd,tempBuf,strlen(tempBuf)+1,0,
            (struct sockaddr *)&client,sin_size);
        if (!strcmp(msg,"quit")) break;
        break;
 
⑵客户器端(发送端)程序:
客户端程序可以在选择在Linux下运行,或者在Windows下运行,下面分别说明如何具体实现:
 
㈠Linux下:
我的Linux系统版本为RedHat 9,在Linux下的开发程序,由于没有像VC之类的强大开发工具,所以编程比较麻烦,调试起来也不方便,Linux下的程序采用纯C编写,本程序没有编写图形界面,只开发了一个类似Windows控制台的程序,在功能上实现了PC与实验箱之间的通信,效果图如下:
附:关键源代码
while (1) {
    int len;
    recvfrom(fd,buf,MAXDATASIZE,0,(struct sockaddr *)&reply,&len);
    printf("Server Message: %s/n",buf);
    break;
    }
 
㈡Windows下:
我的Windows版本为Windows XP,在Windows下编写程序就方便多了,由于有了VC,一切工作就简单了一下,在这里我写了两个版本的程序:
1、 Windows控制台程序
2、 图形界面程序
下面分别说明:
1、Windows控制台程序
本程序采用VC6编写,Windows下编写网络程序与在Linux下编写不太一样,主要是socket的调用有较大的不同,此外VC6主要采用C++语言,效果图如下:
附:关键源代码
while(1)
    {
        printf("Please input data:/n");
        gets(sendBuf);
        sendto(sockClient,sendBuf,strlen(sendBuf)+1,0,
            (SOCKADDR*)&addrSrv,len);
        recvfrom(sockClient,recvBuf,100,0,(SOCKADDR*)&addrSrv,&len);
        if('q'==recvBuf[0])
        {
            sendto(sockClient,"q",strlen("q")+1,0,
                (SOCKADDR*)&addrSrv,len);
            printf("Chat end!/n");
            break;
        }
        sprintf(tempBuf,"%s say : %s",inet_ntoa(addrSrv.sin_addr),recvBuf);
        printf("%s/n",tempBuf);
}
 
2、图形界面程序
本程序采用VC6编写,VC6提供了强大的图形界面程序编写工具,让我们开发图形界面程序十分方便,效果图如下:
附:关键源代码
while(TRUE)
    {
        retval=recvfrom(sock,recvBuf,200,0,(SOCKADDR*)&addrFrom,&len);
        if(SOCKET_ERROR==retval)
            break;
        sprintf(tempBuf,"%s说: %s",inet_ntoa(addrFrom.sin_addr),recvBuf);
        ::PostMessage(hwnd,WM_RECVDATA,0,(LPARAM)tempBuf);
    }
void CChatDlg::OnRecvData(WPARAM wParam,LPARAM lParam)
{
    str=(char*)lParam;
    GetDlgItemText(IDC_EDIT_RECV,strTemp);
    str+="/r/n";
    str+=strTemp;
    SetDlgItemText(IDC_EDIT_RECV,str);
}
void CChatDlg::OnBtnSend()
{
DWORD dwIP;
    ((CIPAddressCtrl*)GetDlgItem(IDC_IPADDRESS1))->GetAddress(dwIP);
SOCKADDR_IN addrTo;
    addrTo.sin_family=AF_INET;
    addrTo.sin_port=htons(1234);
    addrTo.sin_addr.S_un.S_addr=htonl(dwIP);
CString strSend;
    GetDlgItemText(IDC_EDIT_SEND,strSend);
    sendto(m_socket,strSend,strSend.GetLength()+1,0,
        (SOCKADDR*)&addrTo,sizeof(SOCKADDR));
    char tempBuf2[300];
    sprintf(tempBuf2,"对%s说: %s",inet_ntoa(addrTo.sin_addr),strSend);
    //GetDlgItemText(IDC_EDIT_RECV,strTemp);
    str+="/r/n";
    str+=tempBuf2;
    SetDlgItemText(IDC_EDIT_RECV,str);
    SetDlgItemText(IDC_EDIT_SEND,"");
}
 
 
六、结论:
这次UPD协议的实现基本完成了PC和实验箱之间通过有线的以太网实现最基本的通讯,最关键的步骤是熟悉socket的编程。
 
 
参考文献:
〔1〕华恒HHARM9-EDU实验指导书(上,中,下)
〔2〕Brian W.Kernighan,Dennis M.Ritchie C程序设计语言(第2版·新版) 机械工业出版社 2004.1
〔3〕喻志虎 UNIX平台下C语言编程   清华大学出版社 2001.10
〔4〕侯捷    深入浅出MFC(第二版) 华中科技大学出版社 2001.1