int aiptoi(char * pszip,unsigned int* piip) {
char psziphere[17],*psztmp1,*psztmp2,*pchar; /*定义指针*/ int i;
bzero(psziphere,17); /*清空将要进行操作的数组*/
strcpy(psziphere,pszip); /*将要转换的IP地址存入该数组*/ strcat(psziphere,\ /*在IP地址串的末尾加“·”*/ for(i=0,psztmp1=psziphere,pchar=(char )piip;i<4;i++) /*循环4次,将“·”转变成0,并将字符串型转换成整型*/ {
if((psztmp2=strstr(psztmp1,\/*psztmp2返回指向字符“·”位置的指针*/ return 0; psztmp2[0]=0;
(pchar+i)=atoi(psztmp1); /*调用atoi( )函数,将字符串转换成整数*/ psztmp1=psztmp2+1; /*指针psatmp1移到下一段的开始*/ }
return 1; }
int main(int argc,char ** argv) {
int sockfd,numbytes; unsigned int uiip; char buf[MAXDATASIZE]; int i;
struct sockaddr_in servaddr;
if(!aiptoi(argv[1],&uiip)||argc<=1) /*检查IP地址格式是否正确及IP是否输入*/ {
printf(\ return 0; }
if ((sockfd = socket(AF_INET,SOCK_STREAM,0))= =?1) /*建立流式套接字描述符*/ { perror(\ exit(1); }
/*给定主机信息*/
servaddr.sin_family=AF_INET; servaddr.sin_port=htons(PORT); bzero(&(servaddr.sin_zero),8); servaddr.sin_addr.s_addr=uiip;
if(connect(sockfd,(struct sockaddr *)&servaddr,sizeof(struct sockaddr))==?1)
/*建立连接*/ {
printf(\ return 0; }
initgraph( ); /*初始化显示环境*/
if((numbytes=recv(sockfd,buf,MAXDATASIZE,0))== ?1) /*接收服务器传送过来的字符串*/
{ perror(\ exit(1); }
buf[numbytes]='\\0';
clearscreen( ); /*清屏*/
textout(0,0,buf,0xffff,0x1111); /*显示字符串*/ delay( );
clearscreen(); close(sockfd); return 0; }
函数aiptoi()处理的是字符串型的IP地址。首先将该字符串存放入psziphere[ ]数组中,“psztmp1=psziphere”语句将字符串的首地址赋给psztmp1。为了便于使用循环,调用strcat(psziphere,\,将符号“·”添加到字符串尾部。接着循环开始,先找到第一个“·”的位置,psztmp2指向该处,并将该处赋为0(作为字符串的串结束符),调用函数atoi(psztmp1),此时psztmp1指向的是psziphere[ ]数组的首地址,该函数将psztmp1指针所指处到其后面字符串串结束符处(即psztmp2处)的字符串转换成整型数,并存放到pchar[ ]数组中。然后,将psztmp1指针指向psztmp2所指的下一个字符,准备开始下一个循环。以IP地址“192.168.2.100”为例,第一个循环中,psztmp1指向了“192.”的“1”处,而psztmp2指向了“192.168”的“·”处,并将该串改为“196\\0168”;atoi(psztmp1)函数将该串转换成整数192;然后psztmp1指向了字符串“196\\0168”中的“1”;经过四次循环,用“·”分开的四段字符串就可以转换成整数了。
客户端代码相对来说要简单一些,首先通过命令行得到服务器的IP地址,然后创建一个socket,调用connect函数与服务器建立连接,连接成功之后接收从服务器发送过来的数据,最后关闭socket,结束程序。
无连接的客户/服务器程序的在原理上和连接的客户/服务器是一样的,两者的区别在于无连接的客户/服务器中的客户一般不需要建立连接,而且在发送接收数据时,需要指定远端机的地址。
例2:
在PC机上运行一个发送程序,将一文件(图片或文本文件)通过网口传送到开发板,并在LCD上显示该文件。该程序的流程如图2所示。
调用库函数及预定义 初始化,定义变量指针缓冲区和文件操作符号 创建套接字并设置属性 调用转换IP地址 IP地址解析错误 打开位图文件 传送已完成 读文件写协议头及数据 从缓冲发送协议头及数据 关闭位图 断开连接 退出 图2 网口通信程序流程图
服务器端发送程序host.c:
#include
#define MYPORT 3000 /*定义服务器的监听端口*/
#define BACKLOG 10 /*BACKLOG指定在请求队列中允许的最大请求数,进入的连接请求将在队列中等待accept()函数接受它们*/ int main( )
{int sock_fd,new_fd; /*sock_fd,new_fd是套接字描述*/ char filename[20]; /*存放要传送文件的文件名*/ struct sockaddr_in my_addr; /*服务器的地址结构体*/ struct sockaddr_in their_addr; /*主机的地址结构体*/ int sin_size; FILE *fp;
char szsendbuf[1024],head[8]; /*发送数据缓冲区大小为1K*/ int nsize, allsize=0;; int *phead=head+4;
if((sock_fd=socket(AF_INET,SOCK_STREAM,0))== ?1) /*建立流式套接字描述符/ { perror(\exit(1); }
/*服务器结构体的地址赋初值*/ my_addr.sin_family=AF_INET;
my_addr.sin_port=htons(MYPORT); /*服务器的端口号3000*/ my_addr.sin_addr.s_addr=INADDR_ANY;
bzero(&(my_addr.sin_zero),8); /*填充0,凑齐长度*/
if(bind(sock_fd,(struct sockaddr*)&my_addr,sizeof(struct sockaddr))= = ?1) /*绑定*/
{ perror(\绑定失败*/ exit(1); }
if(listen(sock_fd,BACKLOG)= = ?1) /*监听端口是否有请求*/ { perror(\监听失败*/ exit(1); }
while(1)
{ sin_size=sizeof(struct sockaddr_in);
if ((new_fd=accept(sock_fd,(struct sockaddr *)&their_addr,&sin_size))== ?1) { perror(\ continue; }
printf(\read(new_fd,filename,20); /*从端口读文件名*/ printf(\
if((fp=fopen(filename,\打开文件*/ { printf(\ exit(1) ; }

