⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 linux网络编程--2. 初等网络函数介绍(tcp).html

📁 Linux网络编程
💻 HTML
📖 第 1 页 / 共 2 页
字号:
</tr><td align=center><table border="0" width="80%"  cellspacing="0" cellpadding="0" align=center><tr><td valign=top><font color=#cccccc>&nbsp;&nbsp;Linux系统是通过提供套接字(socket)来进行网络编程的.网络程序通过socket和其它几个函数的调用,会返回一个&nbsp;通讯的文件描述符,我们可以将这个描述符看成普通的文件的描述符来操作,这就是linux的设备无关性的&nbsp;好处.我们可以通过向描述符读写操作实现网络之间的数据交流.&nbsp;
<br>
<br>2.1&nbsp;socket&nbsp;
<br>int&nbsp;socket(int&nbsp;domain,&nbsp;int&nbsp;type,int&nbsp;protocol)&nbsp;
<br>
<br>&nbsp;&nbsp;domain:说明我们网络程序所在的主机采用的通讯协族(AF_UNIX和AF_INET等).&nbsp;AF_UNIX只能够用于单一的Unix系统进程间通信,而AF_INET是针对Internet的,因而可以允许在远程&nbsp;主机之间通信(当我们&nbsp;man&nbsp;socket时发现&nbsp;domain可选项是&nbsp;PF_*而不是AF_*,因为glibc是posix的实现&nbsp;所以用PF代替了AF,不过我们都可以使用的).&nbsp;
<br>
<br>&nbsp;&nbsp;type:我们网络程序所采用的通讯协议(SOCK_STREAM,SOCK_DGRAM等)&nbsp;SOCK_STREAM表明我们用的是TCP协议,这样会提供按顺序的,可靠,双向,面向连接的比特流.&nbsp;SOCK_DGRAM&nbsp;表明我们用的是UDP协议,这样只会提供定长的,不可靠,无连接的通信.&nbsp;
<br>
<br>&nbsp;&nbsp;protocol:由于我们指定了type,所以这个地方我们一般只要用0来代替就可以了&nbsp;socket为网络通讯做基本的准备.成功时返回文件描述符,失败时返回-1,看errno可知道出错的详细情况.&nbsp;
<br>
<br>
<br>2.2&nbsp;bind&nbsp;
<br>int&nbsp;bind(int&nbsp;sockfd,&nbsp;struct&nbsp;sockaddr&nbsp;*my_addr,&nbsp;int&nbsp;addrlen)&nbsp;
<br>
<br>&nbsp;&nbsp;sockfd:是由socket调用返回的文件描述符.&nbsp;
<br>
<br>&nbsp;&nbsp;addrlen:是sockaddr结构的长度.&nbsp;
<br>
<br>&nbsp;&nbsp;my_addr:是一个指向sockaddr的指针.&nbsp;在<linux/socket.h>中有&nbsp;sockaddr的定义&nbsp;
<br>
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;struct&nbsp;sockaddr{
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unisgned&nbsp;short&nbsp;&nbsp;as_family;
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;char&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sa_data[14];
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;};
<br>
<br>&nbsp;&nbsp;不过由于系统的兼容性,我们一般不用这个头文件,而使用另外一个结构(struct&nbsp;sockaddr_in)&nbsp;来代替.在<linux/in.h>中有sockaddr_in的定义&nbsp;
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;struct&nbsp;sockaddr_in{
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unsigned&nbsp;short&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sin_family;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unsigned&nbsp;short&nbsp;int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sin_port;
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;struct&nbsp;in_addr&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sin_addr;
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unsigned&nbsp;char&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sin_zero[8];
<br>
<br>&nbsp;&nbsp;我们主要使用Internet所以sin_family一般为AF_INET,sin_addr设置为INADDR_ANY表示可以&nbsp;和任何的主机通信,sin_port是我们要监听的端口号.sin_zero[8]是用来填充的.&nbsp;bind将本地的端口同socket返回的文件描述符捆绑在一起.成功是返回0,失败的情况和socket一样&nbsp;
<br>
<br>2.3&nbsp;listen&nbsp;
<br>int&nbsp;listen(int&nbsp;sockfd,int&nbsp;backlog)&nbsp;
<br>
<br>sockfd:是bind后的文件描述符.&nbsp;
<br>
<br>backlog:设置请求排队的最大长度.当有多个客户端程序和服务端相连时,&nbsp;使用这个表示可以介绍的排队长度.&nbsp;listen函数将bind的文件描述符变为监听套接字.返回的情况和bind一样.&nbsp;
<br>
<br>
<br>2.4&nbsp;accept&nbsp;
<br>int&nbsp;accept(int&nbsp;sockfd,&nbsp;struct&nbsp;sockaddr&nbsp;*addr,int&nbsp;*addrlen)&nbsp;
<br>
<br>sockfd:是listen后的文件描述符.&nbsp;
<br>
<br>addr,addrlen是用来给客户端的程序填写的,服务器端只要传递指针就可以了.&nbsp;bind,listen和accept是服务器端用的函数,accept调用时,服务器端的程序会一直阻塞到有一个&nbsp;客户程序发出了连接.&nbsp;accept成功时返回最后的服务器端的文件描述符,这个时候服务器端可以向该描述符写信息了.&nbsp;失败时返回-1&nbsp;
<br>
<br>
<br>2.5&nbsp;connect&nbsp;
<br>int&nbsp;connect(int&nbsp;sockfd,&nbsp;struct&nbsp;sockaddr&nbsp;*&nbsp;serv_addr,int&nbsp;addrlen)&nbsp;
<br>
<br>sockfd:socket返回的文件描述符.&nbsp;
<br>
<br>serv_addr:储存了服务器端的连接信息.其中sin_add是服务端的地址&nbsp;
<br>
<br>addrlen:serv_addr的长度&nbsp;
<br>
<br>connect函数是客户端用来同服务端连接的.成功时返回0,sockfd是同服务端通讯的文件描述符&nbsp;失败时返回-1.&nbsp;
<br>
<br>
<br>2.6&nbsp;实例&nbsp;
<br>
<br>服务器端程序
<br>
<br>
<br>/*******&nbsp;服务器程序&nbsp;&nbsp;(server.c)&nbsp;************/
<br>#include&nbsp;<stdlib.h>
<br>#include&nbsp;<stdio.h>
<br>#include&nbsp;<errno.h>
<br>#include&nbsp;<string.h>
<br>#include&nbsp;<netdb.h>
<br>#include&nbsp;<sys/types.h>
<br>#include&nbsp;<netinet/in.h>
<br>#include&nbsp;<sys/socket.h>
<br>
<br>int&nbsp;main(int&nbsp;argc,&nbsp;char&nbsp;*argv[])
<br>{
<br>&nbsp;int&nbsp;sockfd,new_fd;
<br>&nbsp;struct&nbsp;sockaddr_in&nbsp;server_addr;
<br>&nbsp;struct&nbsp;sockaddr_in&nbsp;client_addr;
<br>&nbsp;int&nbsp;sin_size,portnumber;
<br>&nbsp;char&nbsp;hello[]="Hello!&nbsp;Are&nbsp;You&nbsp;Fine?\n";
<br>
<br>&nbsp;if(argc!=2)
<br>&nbsp;{
<br>&nbsp;&nbsp;fprintf(stderr,"Usage:%s&nbsp;portnumber\a\n",argv[0]);
<br>&nbsp;&nbsp;exit(1);
<br>&nbsp;}
<br>&nbsp;
<br>&nbsp;if((portnumber=atoi(argv[1]))<0)
<br>&nbsp;{
<br>&nbsp;&nbsp;fprintf(stderr,"Usage:%s&nbsp;portnumber\a\n",argv[0]);
<br>&nbsp;&nbsp;exit(1);
<br>&nbsp;}
<br>
<br>/*&nbsp;服务器端开始建立socket描述符&nbsp;*/
<br>&nbsp;if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)&nbsp;&nbsp;
<br>&nbsp;{
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fprintf(stderr,"Socket&nbsp;error:%s\n\a",strerror(errno));
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit(1);
<br>&nbsp;}
<br>
<br>/*&nbsp;服务器端填充&nbsp;sockaddr结构&nbsp;&nbsp;*/&nbsp;
<br>&nbsp;bzero(&server_addr,sizeof(struct&nbsp;sockaddr_in));
<br>&nbsp;server_addr.sin_family=AF_INET;
<br>&nbsp;server_addr.sin_addr.s_addr=htonl(INADDR_ANY);
<br>&nbsp;server_addr.sin_port=htons(portnumber);
<br>&nbsp;
<br>/*&nbsp;捆绑sockfd描述符&nbsp;&nbsp;*/&nbsp;
<br>&nbsp;if(bind(sockfd,(struct&nbsp;sockaddr&nbsp;*)(&server_addr),sizeof(struct&nbsp;sockaddr))==-1)
<br>&nbsp;{
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fprintf(stderr,"Bind&nbsp;error:%s\n\a",strerror(errno));
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit(1);
<br>&nbsp;}
<br>&nbsp;
<br>/*&nbsp;监听sockfd描述符&nbsp;&nbsp;*/
<br>&nbsp;if(listen(sockfd,5)==-1)
<br>&nbsp;{
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fprintf(stderr,"Listen&nbsp;error:%s\n\a",strerror(errno));
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit(1);
<br>&nbsp;}
<br>
<br>&nbsp;while(1)
<br>&nbsp;{
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;服务器阻塞,直到客户程序建立连接&nbsp;&nbsp;*/
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sin_size=sizeof(struct&nbsp;sockaddr_in);
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if((new_fd=accept(sockfd,(struct&nbsp;sockaddr&nbsp;*)(&client_addr),&sin_size))==-1)
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fprintf(stderr,"Accept&nbsp;error:%s\n\a",strerror(errno));
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit(1);
<br>&nbsp;&nbsp;&nbsp;&nbsp;}
<br>
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fprintf(stderr,"Server&nbsp;get&nbsp;connection&nbsp;from&nbsp;%s\n",
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;inet_ntoa(client_addr.sin_addr));
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(write(new_fd,hello,strlen(hello))==-1)
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fprintf(stderr,"Write&nbsp;Error:%s\n",strerror(errno));
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit(1);
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
<br>/*&nbsp;这个通讯已经结束&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;close(new_fd);
<br>/*&nbsp;循环下一个&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/&nbsp;&nbsp;
<br>&nbsp;&nbsp;}
<br>&nbsp;close(sockfd);
<br>&nbsp;exit(0);
<br>}
<br>
<br>
<br>客户端程序
<br>
<br>/*******&nbsp;客户端程序&nbsp;&nbsp;client.c&nbsp;************/
<br>#include&nbsp;<stdlib.h>
<br>#include&nbsp;<stdio.h>
<br>#include&nbsp;<errno.h>
<br>#include&nbsp;<string.h>
<br>#include&nbsp;<netdb.h>
<br>#include&nbsp;<sys/types.h>
<br>#include&nbsp;<netinet/in.h>
<br>#include&nbsp;<sys/socket.h>
<br>
<br>int&nbsp;main(int&nbsp;argc,&nbsp;char&nbsp;*argv[])
<br>{
<br>&nbsp;int&nbsp;sockfd;
<br>&nbsp;char&nbsp;buffer[1024];
<br>&nbsp;struct&nbsp;sockaddr_in&nbsp;server_addr;
<br>&nbsp;struct&nbsp;hostent&nbsp;*host;
<br>&nbsp;int&nbsp;portnumber,nbytes;
<br>
<br>&nbsp;if(argc!=3)
<br>&nbsp;{
<br>&nbsp;&nbsp;fprintf(stderr,"Usage:%s&nbsp;hostname&nbsp;portnumber\a\n",argv[0]);
<br>&nbsp;&nbsp;exit(1);
<br>&nbsp;}
<br>&nbsp;
<br>&nbsp;if((host=gethostbyname(argv[1]))==NULL)
<br>&nbsp;{
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fprintf(stderr,"Gethostname&nbsp;error\n");
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit(1);
<br>&nbsp;}
<br>
<br>&nbsp;if((portnumber=atoi(argv[2]))<0)
<br>&nbsp;{
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fprintf(stderr,"Usage:%s&nbsp;hostname&nbsp;portnumber\a\n",argv[0]);
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit(1);
<br>&nbsp;}
<br>&nbsp;
<br>/*&nbsp;客户程序开始建立&nbsp;sockfd描述符&nbsp;&nbsp;*/
<br>&nbsp;if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)
<br>&nbsp;{
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fprintf(stderr,"Socket&nbsp;Error:%s\a\n",strerror(errno));
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit(1);
<br>&nbsp;}
<br>
<br>/*&nbsp;客户程序填充服务端的资料&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/
<br>&nbsp;bzero(&server_addr,sizeof(server_addr));
<br>&nbsp;server_addr.sin_family=AF_INET;
<br>&nbsp;server_addr.sin_port=htons(portnumber);
<br>&nbsp;server_addr.sin_addr=*((struct&nbsp;in_addr&nbsp;*)host->h_addr);
<br>&nbsp;
<br>/*&nbsp;客户程序发起连接请求&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/&nbsp;
<br>&nbsp;if(connect(sockfd,(struct&nbsp;sockaddr&nbsp;*)(&server_addr),sizeof(struct&nbsp;sockaddr))==-1)
<br>{
<br>&nbsp;&nbsp;fprintf(stderr,"Connect&nbsp;Error:%s\a\n",strerror(errno));
<br>&nbsp;&nbsp;exit(1);
<br>}
<br>
<br>/*&nbsp;连接成功了&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/
<br>if((nbytes=read(sockfd,buffer,1024))==-1)
<br>{
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fprintf(stderr,"Read&nbsp;Error:%s\n",strerror(errno));
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit(1);
<br>&nbsp;}
<br>&nbsp;buffer[nbytes]='\0';
<br>&nbsp;printf("I&nbsp;have&nbsp;received:%s\n",buffer);
<br>/*&nbsp;结束通讯&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/
<br>&nbsp;close(sockfd);
<br>&nbsp;exit(0);
<br>}
<br>
<br>
<br>MakeFile
<br>这里我们使用GNU&nbsp;的make实用程序来编译.&nbsp;关于make的详细说明见&nbsp;Make&nbsp;使用介绍&nbsp;
<br>
<br>#########&nbsp;&nbsp;Makefile&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;###########
<br>all:server&nbsp;client
<br>server:server.c
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;gcc&nbsp;$^&nbsp;-o&nbsp;$@
<br>client:client.c
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;gcc&nbsp;$^&nbsp;-o&nbsp;$@
<br>
<br>运行make后会产生两个程序server(服务器端)和client(客户端)&nbsp;先运行./server&nbsp;portnumber&&nbsp;(portnumber随便取一个大于1204且不在/etc/services中出现的号码&nbsp;就用8888好了),然后运行&nbsp;./client&nbsp;localhost&nbsp;8888&nbsp;看看有什么结果.&nbsp;(你也可以用telnet和netstat试一试.)&nbsp;上面是一个最简单的网络程序,不过是不是也有点烦.上面有许多函数我们还没有解释.&nbsp;我会在下一章进行的详细的说明.&nbsp;
<br>
<br>
<br>2.7&nbsp;总结&nbsp;
<br>总的来说网络程序是由两个部分组成的--客户端和服务器端.它们的建立步骤一般是:&nbsp;
<br>
<br>服务器端
<br>socket-->bind-->listen-->accept&nbsp;
<br>
<br>客户端
<br>socket-->connect&nbsp;
<br></font></td></tr><tr><td><hr></td></tr><form method=post action=/cgi-bin/find.cgi><tr><td><b>相关文章</b>  关键词 <input type=text name=key value='Linux网络编程'> <input type=submit value=搜索></td></tr></form><tr><td><a href=/a4/b7/20010508/111655.html>Linux网络编程--1. Linux网络知识介绍</a> <small>(2001-05-08 11:16:55)</small></font><br></td></tr><tr><td>&nbsp;</td></tr></table></td></tr><tr>  <td width="100%" height="2" colspan="5" bgcolor="#D09F0D"><img src="/images/c.gif" width=1 height=1></td> </tr><tr>    <td width="100%" height="40" colspan="5" valign=top><p align="center"><font color=#ffffff>&copy; &nbsp;&nbsp;樊强制作 欢迎分享 2001 </font></p></td>  </tr></table></center></div><img src="/cgi-bin/pagehit.cgi?filename=a4/b7/20010508/111934.html" width=1 height=1></body></html>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -