📄 linuxsocket.htm
字号:
sockaddr)) == -1) { <BR>perror("connect出错!"); <BR>exit(1); <BR>} <BR> if
((recvbytes=recv(sockfd, buf, MAXDATASIZE, 0)) ==-1) { <BR>perror("recv出错!");
<BR>exit(1); <BR>} <BR> buf[recvbytes] = '\0'; <BR> printf("Received: %s",buf);
<BR> close(sockfd); <BR>}
<BR> 客户端程序首先通过服务器域名获得服务器的IP地址,然后创建一个socket,调用connect函数与服务器建立连接,连接成功之后接收从服务器发送过来的数据,最后关闭socket。
<BR> 函数gethostbyname()是完成域名转换的。由于IP地址难以记忆和读写,所以为了方便,人们常常用域名来表示主机,这就需要进行域名和IP地址的转换。函数原型为:
<BR> struct hostent *gethostbyname(const char *name);
<BR> 函数返回为hosten的结构类型,它的定义如下: <BR> struct hostent { <BR> char *h_name; /*
主机的官方域名 */ <BR> char **h_aliases; /* 一个以NULL结尾的主机别名数组 */ <BR> int
h_addrtype; /* 返回的地址类型,在Internet环境下为AF-INET */ <BR> int h_length; /* 地址的字节长度 */
<BR> char **h_addr_list; /* 一个以0结尾的数组,包含该主机的所有地址*/ <BR> }; <BR> #define
h_addr h_addr_list[0] /*在h-addr-list中的第一个地址*/ <BR> 当
gethostname()调用成功时,返回指向struct
hosten的指针,当调用失败时返回-1。当调用gethostbyname时,你不能使用perror()函数来输出错误信息,而应该使用herror()函数来输出。
<BR><BR> 无连接的客户/服务器程序的在原理上和连接的客户/服务器是一样的,两者的区别在于无连接的客户/服务器中的客户一般不需要建立连接,而且在发送接收数据时,需要指定远端机的地址。
<BR><BR>阻塞和非阻塞
<BR> 阻塞函数在完成其指定的任务以前不允许程序调用另一个函数。例如,程序执行一个读数据的函数调用时,在此函数完成读操作以前将不会执行下一程序语句。当服务器运行到accept语句时,而没有客户连接服务请求到来,服务器就会停止在accept语句上等待连接服务请求的到来。这种情况称为阻塞(blocking)。而非阻塞操作则可以立即完成。比如,如果你希望服务器仅仅注意检查是否有客户在等待连接,有就接受连接,否则就继续做其他事情,则可以通过将Socket设置为非阻塞方式来实现。非阻塞socket在没有客户在等待时就使accept调用立即返回。
<BR> #include <unistd.h> <BR> #include <fcntl.h> <BR> ……
<BR>sockfd = socket(AF_INET,SOCK_STREAM,0);
<BR>fcntl(sockfd,F_SETFL,O_NONBLOCK); <BR>……
<BR> 通过设置socket为非阻塞方式,可以实现"轮询"若干Socket。当企图从一个没有数据等待处理的非阻塞Socket读入数据时,函数将立即返回,返回值为-1,并置errno值为EWOULDBLOCK。但是这种"轮询"会使CPU处于忙等待方式,从而降低性能,浪费系统资源。而调用
select()会有效地解决这个问题,它允许你把进程本身挂起来,而同时使系统内核监听所要求的一组文件描述符的任何活动,只要确认在任何被监控的文件描述符上出现活动,select()调用将返回指示该文件描述符已准备好的信息,从而实现了为进程选出随机的变化,而不必由进程本身对输入进行测试而浪费
CPU开销。Select函数原型为: <BR>int select(int numfds,fd_set *readfds,fd_set *writefds,
<BR>fd_set *exceptfds,struct timeval *timeout);
<BR> 其中readfds、writefds、exceptfds分别是被select()监视的读、写和异常处理的文件描述符集合。如果你希望确定是否可以从标准输入和某个socket描述符读取数据,你只需要将标准输入的文件描述符0和相应的sockdtfd加入到readfds集合中;numfds的值是需要检查的号码最高的文件描述符加1,这个例子中numfds的值应为sockfd+1;当select返回时,readfds将被修改,指示某个文件描述符已经准备被读取,你可以通过FD_ISSSET()来测试。为了实现fd_set中对应的文件描述符的设置、复位和测试,它提供了一组宏:
<BR> FD_ZERO(fd_set *set)----清除一个文件描述符集; <BR> FD_SET(int fd,fd_set
*set)----将一个文件描述符加入文件描述符集中; <BR> FD_CLR(int fd,fd_set
*set)----将一个文件描述符从文件描述符集中清除; <BR> FD_ISSET(int fd,fd_set
*set)----试判断是否文件描述符被置位。 <BR> Timeout参数是一个指向struct
timeval类型的指针,它可以使select()在等待timeout长时间后没有文件描述符准备好即返回。struct timeval数据结构为:
<BR> struct timeval { <BR> int tv_sec; /* seconds */ <BR> int tv_usec; /*
microseconds */ <BR>}; <BR><BR>POP3客户端实例
<BR> 下面的代码实例基于POP3的客户协议,与邮件服务器连接并取回指定用户帐号的邮件。与邮件服务器交互的命令存储在字符串数组POPMessage中,程序通过一个do-while循环依次发送这些命令。
<BR>#include<stdio.h> <BR>#include <stdlib.h> <BR>#include
<errno.h> <BR>#include <string.h> <BR>#include <netdb.h>
<BR>#include <sys/types.h> <BR>#include <netinet/in.h> <BR>#include
<sys/socket.h> <BR>#define POP3SERVPORT 110 <BR>#define MAXDATASIZE 4096
<BR><BR>main(int argc, char *argv[]){ <BR>int sockfd; <BR>struct hostent *host;
<BR>struct sockaddr_in serv_addr; <BR>char *POPMessage[]={ <BR>"USER
userid\r\n", <BR>"PASS password\r\n", <BR>"STAT\r\n", <BR>"LIST\r\n", <BR>"RETR
1\r\n", <BR>"DELE 1\r\n", <BR>"QUIT\r\n", <BR>NULL <BR>}; <BR>int iLength;
<BR>int iMsg=0; <BR>int iEnd=0; <BR>char buf[MAXDATASIZE];
<BR><BR>if((host=gethostbyname("your.server"))==NULL) {
<BR>perror("gethostbyname error"); <BR>exit(1); <BR>} <BR>if ((sockfd =
socket(AF_INET, SOCK_STREAM, 0)) == -1){ <BR>perror("socket error");
<BR>exit(1); <BR>} <BR>serv_addr.sin_family=AF_INET;
<BR>serv_addr.sin_port=htons(POP3SERVPORT); <BR>serv_addr.sin_addr = *((struct
in_addr *)host->h_addr); <BR>bzero(&(serv_addr.sin_zero),8); <BR>if
(connect(sockfd, (struct sockaddr *)&serv_addr,sizeof(struct
sockaddr))==-1){ <BR>perror("connect error"); <BR>exit(1); <BR>} <BR><BR>do {
<BR>send(sockfd,POPMessage[iMsg],strlen(POPMessage[iMsg]),0); <BR>printf("have
sent: %s",POPMessage[iMsg]);
<BR><BR>iLength=recv(sockfd,buf+iEnd,sizeof(buf)-iEnd,0); <BR>iEnd+=iLength;
<BR>buf[iEnd]='\0'; <BR>printf("received: %s,%d\n",buf,iMsg); <BR><BR>iMsg++;
<BR>} while (POPMessage[iMsg]); <BR><BR>close(sockfd); <BR>}</SPAN> </P>
<P></P>
<P class=diaryFoot>【作者: <A
onclick="window.open('http://publishblog.blogchina.com/blog/postMessage.b?receiver=1311348','发送短消息','width=520, height=455')"
href="javascript:void(0);">红谷/海之屿</A>】【访问统计:
<SCRIPT language=JavaScript
src="Linux环境下的Socket--我的梦在飞翔-红谷-海之屿.files/PageServlet.htm"></SCRIPT>
】【2005年12月9日 星期五 13:51】【 <A
href="javascript:void(keyit=window.open('http://blogmark.blogchina.com/jsp/key/quickaddkey.jsp?k='+encodeURI('Linux环境下的Socket')+'&u='+encodeURI('http://redvale.blogchina.com/redvale/3822099.html')+'&c='+encodeURI(''),'keyit','scrollbars=no,width=500,height=430,status=no,resizable=yes'));keyit.focus();">加入博采</A>】【<A
href="javascript:window.print();">打印</A>】 </TD></P></DIV>
<DIV class=operation><A name=trackback>
<H3>Trackback</H3></A>
<P class=trackback>你可以使用这个链接引用该篇文章
http://publishblog.blogchina.com/blog/tb.b?diaryID=3822099 </P></DIV>
<DIV class=operation><A name=relatedDiary>
<H3>博客手拉手</H3></A>
<TABLE>
<TBODY>
<TR>
<TD align=left><A title=socket
href="http://theredbox.blogchina.com/3708811.html"
target=_blank>socket</A></TD>
<TD align=right><A title=http://theredbox.blogchina.com/
href="http://theredbox.blogchina.com/" target=_blank>theredbox</A></TD></TR>
<TR>
<TD align=left><A title=linux教程
href="http://heyingworld.blogchina.com/3653624.html"
target=_blank>linux教程</A></TD>
<TD align=right><A title=http://heyingworld.blogchina.com/
href="http://heyingworld.blogchina.com/"
target=_blank>heyingworld</A></TD></TR>
<TR>
<TD align=left><A title=Linux学习日记
href="http://zth490.blogchina.com/3741037.html"
target=_blank>Linux学习日记</A></TD>
<TD align=right><A title=http://zth490.blogchina.com/
href="http://zth490.blogchina.com/" target=_blank>小好</A></TD></TR>
<TR>
<TD align=left><A title=Linux守护进程
href="http://standqm.blogchina.com/3690651.html"
target=_blank>Linux守护进程</A></TD>
<TD align=right><A title=http://standqm.blogchina.com/
href="http://standqm.blogchina.com/" target=_blank>夜晚星星</A></TD></TR>
<TR>
<TD align=left><A title=学习Linux的心得
href="http://lostmarine.blogchina.com/3705780.html"
target=_blank>学习Linux的心得</A></TD>
<TD align=right><A title=http://lostmarine.blogchina.com/
href="http://lostmarine.blogchina.com/"
target=_blank>他年我若为青帝</A></TD></TR></TBODY></TABLE></DIV>
<DIV class=operation><A name=comment>
<H3>回复</H3></A>
<TABLE cellSpacing=0 cellPadding=0 width=700 border=0>
<TBODY>
<TR align=left>
<TD align=middle rowSpan=2><IMG
src="Linux环境下的Socket--我的梦在飞翔-红谷-海之屿.files/unknowman.gif"> </TD>
<TD colSpan=4>
<H4><A name=comment$(remark.remarkID)>- 评论人:quan</A>
<SPAN> 2006-04-30 09:31:35 <A> <IMG
src="Linux环境下的Socket--我的梦在飞翔-红谷-海之屿.files/linkblog.jpg" border=0> </A>
</SPAN></H4></TD></TR>
<TR align=left>
<TD vAlign=top colSpan=4>
<P class=comment>写的真不错, <BR>我也推荐一篇文章 也是关于socket
http://blog.csdn.net/fengyv/archive/2006/04/12/659980.aspx<BR></P></TD></TR></TBODY></TABLE></DIV>
<DIV class=operation>
<TABLE class=comment cellSpacing=0 cellPadding=0 width=700 border=0>
<FORM id=replyForm method=post><INPUT type=hidden value=1311271 name=blogID>
<INPUT type=hidden value=3822099 name=diaryID> <INPUT type=hidden
value=redvale name=blogDomino>
<SCRIPT>
if(getCookie('userID') == null){
document.write('<tr><td width="70">发布人:</td>');
document.write('<td width="150"> <input name="remark.authorNameFUI" type="text" size="20" class="inputStyle" maxlength="20"></td>');
document.write('<td width="70">邮箱:</td>');
document.write('<td width="435"> <input name="remark.authorEmail" type="text" size="20" class="inputStyle" maxlength="40"></td>');
document.write('</tr><tr><td>主 页:</td>');
document.write('<td colspan="3"> <input name="remark.authorURL" type="text" class="inputStyle" value="HTTP://" size="63" maxlength="100"></td></tr>');
}else{
document.write('<input type="hidden" name="remark.authorNameFUI" value="Blogchina网友">');
}
</SCRIPT>
<TBODY>
<TR>
<TD width=70>验证码:</TD>
<TD><INPUT class=inputStyle maxLength=4 name=validateCode></TD>
<TD> <IMG
src="Linux环境下的Socket--我的梦在飞翔-红谷-海之屿.files/getValidateImg.jpg"
border=0></TD></TR>
<TR align=left>
<TD colSpan=4>评论内容:<BR><TEXTAREA class=textStyle id=remark name=remark.remarkFUI rows=8 cols=60> </TEXTAREA>
</TD></TR>
<TR align=left>
<TD colSpan=4> <INPUT onclick=reply() type=button value=提交>
<INPUT type=reset value=重置> </TD></TR></FORM></TBODY></TABLE></DIV></DIV>
<SCRIPT src="Linux环境下的Socket--我的梦在飞翔-红谷-海之屿.files/extend3.js"
type=text/javascript></SCRIPT>
<DIV id=footer><A href="http://blog.bokee.com/">2003-2004 BOKEE.COM All rights
reserved</A><BR><A href="http://www.blogdriver.com/">Powered by BlogDriver
2.1</A> </DIV></BODY></HTML>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -