




已阅读5页,还剩10页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
用Perl语言进行Socket编程网络编程是一门神秘且复杂的艺术,当然也十分有趣。Perl语言提供了丰富的TCP/IP网络函数,所有这些函数都直接来源于C语言的socket库函数. 由于Perl语言和C语言的socket库函数在型式和使用方法上都是一样的,因此会使用Perl语言进行Socket编程, 当然也就会使用C语言进行Socket编程. 下面是Perl语言中有关的socket库函数列表:一。函数原型 使用说明 socket()socket()系统调用为客户机或服务器创建一个套接字,套接字函数在如下定义:#include#includeint socket(int family, int type, int protocol) 在Linux中family=AF_UNIX.type可以是SOCK_STREAM它是可靠的虽然通讯速度较慢,也可以是SOCK_DGRAM它通讯速度较快但不可靠.如果type=SOCK_STREAM那么protocol=IPPROTO_TCP.如果type=SOCK_DGRAM那么protocol=IPPROTO_UDP.如果出错,函数将返回-1.否则返回一个套接字描述符你可以在程序后面的调用中通过套接字描述符使用这个套接字.套接字创建时没有指定名字.客户机用套接字的名字读写它.这就是如下绑定函数所要做之事.listen()listen()系统调用被服务器所使用.下面有它的定义:#include#includeint listen(int sockfd, int backlog);sockfd是套接字描述符.backlog是在一时间内尚未被决定是否拒绝的连接的号码.一般使用标准值5.如发生错误则返回值小于1.如果这个调用成功,你就已经可以接受连接了.setsockopt()和getsockopt()Linux所提供的socket库含有一个错误(bug).此错误表现为你不能为一个套接字重新启用同一个端口号,即使在你正常关闭该套接字以后.例如,比方说,你编写一个服务器在一个套接字上等待的程序.服务器打开套接字并在其上侦听是没有问题的.无论如何,总有一些原因(不管是正常还是非正常的结束程序)使你的程序需要重新启动.然而重启动后你就不能把它绑定在原来那个端口上了.从bind()系统调用返回的错误代码总是报告说你试图连接的端口已经被别的进程所绑定.问题就是Linux内核在一个绑定套接字的进程结束后从不把端口标记为未用.在大多数UNIX系统中,端口可以被一个进程重复使用,甚至可以被其它进程使用.在Linux中绕开这个问题的办法是,但套接字已经打开但尚未有连接的时候用setsockopt()系统调用在其上设定选项(options).setsockopt()调用设置选项而getsockopt()从给定的套接字取得选项.这里是这些调用的语法:#include#includeint getsockopt(int sockfd, int level, int name, char *value, int *optlen)int setsockopt(int sockfd, int level, int name, char *value, int *optlen)sockfd必须是一个已打开的套接字.level是函数所使用的协议标准(protocol level)(TCP/IP协议使用IPPROTO_TCP,套接字标准的选项实用SOL_SOCKET),选项的名称(name)在套接字说明书中(man page)有详细说明.*value指向为getsockopt()函数所获取的值或setsockopt()函数所设置的值的地址.optlen指针指向一个整数,该整数包含参数以字节计算的长度.其值被getsockopt()设置且其值必须被程序员设定当使用一个经由setsockopt().选项的所有细节可以在使用手册中setsockopt的第二节(setsockopt(2)找到.现在我们再回到Linux的错误上来.当你打开一个套接字时必须同时用下面的代码段来调用setsockopt()函数:#ifdef LINUXopt = 1; len = sizeof(opt);setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&opt,&len); #endif只有当你想让程序不光是在Linux系统下使用时,#ifdef和#endif描述才是必须的.有些UNIX系统可能不支持或不需要SO_REUSEADDR标志.sendto()recvfrom()recvfrom()系统调用是这样定义的:#include #include int recvfrom(int sockfd,const void *message_, /* the pointer to message */int length, /* of message */unsigned int flags, /* of routing, leave 0 */const struct sockaddr * client, /* where to send it */int length ); /* of sockaddr */如果一个信息大得缓冲区都放不下,那么附加信息将被砍掉.该调用可以立即返回,也可以永久的等待.这取决于你把flags设置成什么类型.你甚至可以设置超时(timeout)值.在说明书(man pages)中可以找到recvfrom的更多信息.accept(NEWSOCKET,GENERICSOCKET) 接受请求的socket连接.如果成功,则返回压缩形式的网络地址;否则返回FALSE. 范例: if (!$Connect = accept(NEW,HANDLE) die Connection failed: $!; bind(SOCKET,NAME) 建立NAME与SOCKET的绑定,其中NAME应该是对应socket正确类型的压缩地址. 如果成功,则返回真;否则返回假.在使用socket进行网络编程时,这一函数十分重要,因为它建立了socket句柄与网络上某个地址的关联. 范例: bind(SH,$SocketAddress);connect(SOCKET,NAME) 试图与已经调用了accept()函数并等待建立连接的另外一个进程进行对话. connect()调用被在面向连接的系统中客户机连接服务器时使用.connect()调用必须被用在bind()调用之后.如果成功,则返回真;否则返回假.NAME应该是对应SOCKET句柄正确类型的压缩地址 范例: connect(SOCK,$address) | die Cant connect with remote host: $!; gethostbyaddr(ADDRESS,TYPE) 将压缩形式的网络地址转换为更易于人阅读理解的名字与地址. 当只知道主机的IP地址时,可以使用本函数查询主机名及其他网络信息.它返回一个列表,包含如下信息: ($name, $alias, $addrtype, $length, $address) 其中, $name是与IP地址对应的主机名, $alias是对应$name的其他别名, $addrtype是网络地址的类型, $length是地址的长度, 而$address则是压缩形式IP地址的列表. 二。范例: $PackedAddress = pack(C4, $IPAddr); ($name, $alias, $addrtype, $length, $address) =gethostbyaddr($PackedAddress,2); gethostbyname(NAME) 与上面的gethostbyaddr()函数类似,不过在这里主机名是作为参数.返回的信息格式完全相同. 范例: $Host = ; ($name, $alias, $addrtype, $length, $address) =gethostbyname($Host); IP = unpack(C4,$address0); $HostIP = join(., IP);验证邮箱密码的程序的原码下面的代码在两种操作系统下对263.net和两个POP3服务器严格测试, 证明是成功的. 第一种: 操作系统:Windows 98 中文版 WWW服务器:Apache 1.3.9 for Win Perl 解释器:ActiveState Tool Corp的Perl for Win32 , version 5.005_03 built for MSWin32-x86-object 第二种: 操作系统:Red Hat Linux 6.1 WWW服务器:Apache 1.3.6 for Linux Perl 解释器:version 5.005_03 built for i386-linux 下一页是详细程序#!/usr/bin/perl # test.pl #Author homepage: use strict; use Socket; my $pop3server = 263.net; my $port = 110; $|=1; print Content-type: text/html; print POP3; print ; my ($a,$name,$aliases,$proto,$type,$len,$thataddr,$thisaddr,$i); my $AF_INET = 2; my $SOCK_STREAM = 1; my $sockaddr = S n a4 x8; ($name,$aliases,$proto) = getprotobyname(tcp); ($name,$aliases,$port) = getservbyname($port,tcp) unless $port = /d+$/; ($name,$aliases,$type,$len,$thataddr) = gethostbyname($pop3server); my $this = pack($sockaddr, $AF_INET, 12345, $thisaddr); my $that = pack($sockaddr, $AF_INET, $port, $thataddr); my $mysocket = socket(S, $AF_INET, $SOCK_STREAM, $proto); if ($mysocket) else print 不能打开socket: $!; exit(0); my $mybind = bind(S, $this); if ($mybind) else print 无法绑定!: $!; exit(0); my $myconnect = connect(S,$that); if ($myconnect) else print 连接错误: $!; exit(0); my $BUF = ; my $SenderIP = recv(S, $BUF, 596,0); if ($SenderIP) else print 接收错误: $!; exit(0); if (substr($BUF,0,3) eq +OK) else print POP3服务器出错!; exit(0); my $BUFFER = USER zhangsan; $BUFFER .= chr(13); $BUFFER .= chr(10); my $SENVAL = send(S, $BUFFER,0); if ($SENVAL) else print 发送错误: $!; exit(0); my $BUF = ; my $SenderIP = recv(S, $BUF, 4096,0); if ($SenderIP) else print 接收错误: $!; exit(0); if (substr($BUF,0,3) eq +OK) else print 无此帐号!; exit(0); $BUFFER = PASS 12345678; $BUFFER .= chr(13); $BUFFER .= chr(10); my $SENVAL = send(S, $BUFFER,0); if ($SENVAL) else print 发送错误: $!; exit(0); $BUF = ; my $SenderIP = recv(S, $BUF, 196, 0); if ($SenderIP) else print 接收错误: $!; exit(0); if (substr($BUF,0,3) eq +OK) else print 密码错误!; exit(0); print密码是正确的! 本程序版权归菜瓜乐园 EOF exit(0);三。程序说明面向套接字协议的服务器端 #include #include #include #include #define MY_PORT 6545main(int argc, char *argv)int sockfd, newfd;int cpid; /* child id */struct sockaddr_in servaddr;struct sockaddr_in clientInfo;if (sockfd = socket(AF_INET, SOCK_STREAM, 0) 0)myabort(Unable to create socket);#ifdef LINUXopt = 1; len = sizeof(opt);setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&opt,&len);#endifbzero(char *)&servaddr, sizeof(servaddr);servaddr.sin_family = AF_INET;servaddr.sin_addr.s_addr = htonl(INADDR_ANY);servaddr.sin_family = htons(MY_PORT);/* The htonl (for a long integer) and htons (for short integer) convert* a host oriented byte order * into a network order.*/if (bind(sockfd,(struct sockaddr *)&servaddr,sizeof(struct sockaddr) 0)myabort(Unable to bind socket);listen(sockfd,5);for (;)/* wait here */newfd=accept(sockfd,(struct sockaddr *)&clientInfo,sizeof(struct sockaddr);if (newfd 0)myabort(Unable to accept on socket);if (cpid = fork() 0)myabort(Unable to fork on accept);else if (cpid = 0) /* child */close(sockfd); /* no need for original */do_your_thing(newfd);exit(0);close(newfd); /* in the parent */)在面向连接的协议的程序中,服务器执行以下函数:调用socket()函数创建一个套接字.调用bind()函数把自己绑定在一个地址上调用listen()函数侦听连接调用accept()函数接受所有引入的请求调用read()函数获取引入的信息然后调用write()回答-客户端函数#include #include #include #include #define MY_PORT 6545#define MY_HOST_ADDR int getServerSocketId()int fd, len;struct sockaddr_in unix_addr;/* create a Unix domain stream socket */if ( (fd = socket(AF_UNIX, SOCK_STREAM, 0) 0)return(-1);#ifdef LINUXopt = 1; len = sizeof(opt);setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&opt,&len);#endif/* fill socket address structurew/our address */memset(&unix_addr, 0, sizeof(unix_addr);unix_addr.sin_family = AF_INET;/* convert internet address to binary value*/unix_addr.sin_addr.s_addr = inet_addr(MY_HOST_ADDR);unix_addr.sin_family = htons(MY_PORT);if (bind(fd, (struct sockaddr *) &unix_addr, len) 0)return(-2);memset(&unix_addr, 0, sizeof(unix_addr);if (connect(fd, (struct sockaddr *) &unix_addr, len) 0)return(-3);return(fd);在面向连接的通信中客户机要做如下一些事:调用socket()函数创建一个套接字调用connect()函数试图连接服务器如果连接成功调用write()函数请求数据,调用read()函数接收引入的应答四。不连接(Connectionless)套接字程序设计 现在让我们来考虑一下不连接的信息交换.其服务器端的原理和面向连接的协议有所不同.服务器并不调用listen和accept而是调用recvfrom().同样,服务器用sendto()函数来应答信息.服务器端程序如下:服务器端#include #include #include #include #define MY_PORT 6545#define MAXM 4096char mesgMAXM;main(int argc, char *argv)int sockfd, newfd;int cpid; /* child id */struct sockaddr_in servaddr;struct sockaddr_in clientInfo;if (sockfd = socket(AF_INET, SOCK_STREAM, 0) 0)myabort(Unable to create socket);#ifdef LINUXopt = 1; len = sizeof(opt);setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&opt,&len);#endifbzero(char *)&servaddr, sizeof(servaddr);servaddr.sin_family = AF_INET;servaddr.sin_addr.s_addr = htonl(INADDR_ANY);servaddr.sin_family = htons(MY_PORT);/* The htonl (for a long integer) and hto
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 跨文化健康行为差异-洞察及研究
- 浙江省2025-2026学年七年级语文上学期第一次月考复习试卷(含答案)
- 数据存储系统的分布式设计与优化方法-洞察及研究
- 部门安全生产培训制度课件
- 部门二级安全培训时长课件
- 避坑房产课件
- 基于循环经济的刮板链废旧部件资源化利用路径探索
- 基于元宇宙技术的虚拟现场重建与跨时空图像传输溯源研究
- 基于AI图像识别的动态分级系统与农业物联网集成瓶颈
- 国际标准对接中国产产床核心部件的供应链韧性研究
- GB/T 23338-2018内燃机增压空气冷却器技术条件
- 癫痫的急救与护理课件
- 海姆立克急救法完整版本课件
- 国家地表水环境质量监测网采测分离实施方案课件
- 控压钻井技术及实践培训讲义工艺课件
- 厚度仪点检表
- 北京市水利工程维修养护定额
- 自然拼读法在小学英语教学中的应用的实践研究
- 无领导小组面试评分表模板
- “自然拼读法在识记单词中的实践研究”课题开题报告
- 第二届上海十佳理财之星参赛作品
评论
0/150
提交评论