UNIX网络编程之第二步之嚼烂基本TCP套接字编程(以简单的TCP客户/服务器回射程序为例)
来源:互联网 发布:js图片自动轮播 编辑:程序博客网 时间:2024/04/30 00:56
讲点废话
在博友的建议下,暂时中断了网络编程的学习,连着看了几天的linux基础视频,现在继续学习UNIX网络编程,在实践中继续学习linux,当然没看完的linux的基础视频还要继续看下去,两者交叉结合着进行。第一篇网络编程的博文只是百度了网上的各种博文,不甚了了的搭建了《UNIX网络编程》书中的环境。并敲进去第一个获得服务器时间的例子。虽然运行成功,但对于其中的原理,一窍不通,这篇博文是则主要是自己对原理的一次整理,虽然理解的可能有偏差,但基本上可以说服自己。 再有就是,受到博友的启发,抛弃UNIX网络编程一书的UNP.H头文件和包裹函数等作者自己搞出来的东东。感觉这样会限制自己以后的开发。UNP.H头文件其实也就是包含了大部分网络程序都需要的许多系统头文件,并定义了所用到的各种常值(如MAXLINE),感觉虽然它比较全,但也让自己不知道自己到底使用了那些头文件,还有就是包裹函数,这玩意好像是作者自己定义的西西(比如说Socket就是socket和错误处理结合了一下),最好还是不用。自己写比较清晰点。
言归正传,进入重点。
1/框架
首先,先给出两个框架,
框架1 基本TCP客户/服务器程序
pid_t pid;int listenfd,connfd;listenfd=socket( . . . );/*fill in sockaddr_in{} with server's well-know port*/bind(listenfd, . . . );listen(listenfd,LISTENQ);for( ; ; ){connfd=accept(listenfd,. . .);/*probably blocks*/if((pid=fork())==0){close(listenfd);/*child closes listening socket*/doit(connfd);/*process the request*/close(connfd);/*child terminates*/exit(0);}close(connfd);/*parent closes connected socket*/}
框架2 典型的并发服务器轮廓
实现任何客户/服务器网络应用所需的所有基本步骤都可通过框架1来阐明,若想开发自己的应用程序,只需修改服务器对来自客户的输入的处理过程。
2/基本TCP套接字编程函数阐释
###1/socket()
函数
int socket(int family,int type,int protocal)
family指明协议族(又称为协议域),可选用如下:
由于我们是IPV4程序,所以这里我们就选用表中的AF_INET来作为family的值
type指明套接字类型其可选范围为
在这里我们type的值选为SOCK_STREAM,至于为什么选用如下值通过下表即明了。
这是第三个参数protocol为0的情况下,socket函数中family和type参数组合的结果,我们的程序是TCP所以可以将第二个参数设为SOCK_STREAM,第三个参数设为0.
当然第三个参数也可以不为0,
当protocol参数不为0的时候,type就可以自由多了。
总的来说根据以上设定确定下来了此次网络通信遵循的是TCP协议。此函数为客户端和服务器端都必须调用的函数(这点从框架图1也可以看出),且协议必须一致,
2/connect函数
connect函数激发出TCP三路握手过程(UDP单路连接过程),而且仅在连接建立成功或出错时返回。出错返回有以下三种情况:如果将这个链接过程想象为打电话的话可以这样说: 1/已经嘟了75s后,仍然没有人接(这是可能对方正在用其他电话在接听其他人的来电),那么此次通话失败,不会再嘟了。(这种情况对应于服务器listen()第二个参数backlog,满了) 2/你想联系的人压根就没有装电话, 3/你想联系的人在火星,地球电话根本通不到火星
connect函数导致当前套接字从closed状态(该套接字自从由socket函数创建以来一直所处的状态)转移到SYN_SENT状态,若成功则再转移到ESTABLISHED状态。若connect失败则该套接字不再可用,必须关闭,我们不能对这样的套接字再次调用connect函数。
connect(int sockfd,const struct sockaddr *servaddr,socklen_t addrlen);
sockfd是由sockfd()函数得到的网络套接字,它可以告知网络通信协议是TCP还是UDP从而告知connect()函数知道到底要进行进行几次握手连接。
知道了要进行几次连接之后还要知道与谁建立连接,因此还要输入服务器的地址(IP地址和端口号),地址结构体指针servaddr和地址结构体长度addrlen担此重任。
此函数仅为客户端所调用。
3/bind函数
bind(int sockfd,const struct sockaddr *myaddr,socklen_t addrlen);
进程可以把一个特定的IP地址(和端口号)捆绑到它的套接字上。对于TCP客户,这就为在该套接字上发送数据指明了源IP(端口)地址。对于TCP服务器,这就限定了该套接字只接受那些目的地址为这个IP地址(和端口号)的客户的连接。TCP客户端通常不需要捆绑,由内核随机分配,而服务器则必须要捆绑并要让其端口号/IP地址为所有客户端所知道。就好比所有的人都可以访问百度,百度不需要知道用户的地址,它为所有人服务,但用户必须知道百度www.baidu.com否则它不知道把自己的请求发送到哪里。
4/listen函数
如果说bind函数通常仅有服务器调用,那么listen()函数则是必须只能由服务器调用。当socket()函数创建一个套接字时。它被认为主动套接字,它可以通过connect()函数来主动连接别人,而服务器则正是这里的别人,被连接被访问,因此listen()函数的作用就是将其定性为被动。这也就是为什么只有服务器才能调用该函数。
listen(int sockfd,int backlog);其中第二个参数为内核应该为相应套接字排队的最大连接个数,可以认为是访问服务器的最大客户机数量。
当进程调用accept时,已完成连接队列中的队头项将返回给进程,或者如果该队列为空,那么进程将被投入睡眠,直到TCP在该队列中放入一项才唤醒他。
5accept函数
int accept(int sockfd,struct sockaddr *cliaddr,socklen_t *addrlen)
作用:返回下一个已完成(三次)连接的描述符或称之为已连接套接字。在此函数中,sockfd为服务器监听套接字。内核为每个由服务器进程接受的客户连接接受创建一个已连接套接字(也就是对于它的TCP三路握手过程已经完成)。当服务器完成对某个特定客户的服务时,相应的已连接套接字就被关闭,但监听套接字在整个有效期内都保持开放,通常我们将第二/三个参数置为空指针,因为我们对客户的身份不感兴趣。
6fork()函数
pid_t fork(void)函数在子进程中返回0,在父进程中返回子进程ID,据此可以区分子进程和父进程。通常情况并发服务器的编写就是如下一种过程:父进程调用accept之后调用fork()将已连接套接字与子进程共享,然后由子进程来处理任务,父进程则立即关闭此次的已连接套接字,回到accept()函数,阻塞于此。
的
- UNIX网络编程之第二步之嚼烂基本TCP套接字编程(以简单的TCP客户/服务器回射程序为例)
- 《unix网络编程》(18)基本UDP套接字 简单客户服务器回射程序及改进
- Unix网络编程之基本TCP套接字编程
- UNIX网络编程——TCP的连接建立与终止、基本TCP客户/服务器套接字函数
- TCP网络编程之echo回射程序
- tcp客户/服务器回射程序之三-----数据格式
- (unix网络编程)tcp回射程序三:多路复用
- (unix网络编程)tcp回射程序一:基本实现
- UNIX网络编程卷1:套接字联网-第5章:TCP客户/服务器程序示例
- 【Unix 网络编程】TCP 客户/服务器简单 Socket 程序
- tcp客户/服务器回射程序之四-----select函数的使用
- Unix网络编程—基本TCP套接字编程
- UNIX网络编程——基本TCP套接字编程
- UNIX网络编程---基本TCP套接字编程(四)
- UNIX网络编程——基本TCP套接字编程
- 《UNIX网络编程》学习笔记:基本TCP套接字编程
- UNIX网络编程3:基本TCP套接字编程
- 《unix网络编程》(19)使用select的TCP和UDP回射程序
- findbugs 错误类型
- webview图片适配解决方案
- POJ 3449 Geometric Shapes(判断几个不同图形的相交,线段相交判断)
- poj 1061 青蛙的约会 (扩展欧几里得模板)
- bashrc和profile的区别
- UNIX网络编程之第二步之嚼烂基本TCP套接字编程(以简单的TCP客户/服务器回射程序为例)
- Codeforces 589J Cleaner Robot(DFS)
- 启动Tomcat提示:指定的服务未安装
- 手动删除Win7系统服务列表中残留服务的操作步骤
- 免费JSON接口
- Nodejs学习 1 -- 入门手上
- iOS6新特征:UICollectionView介绍
- 将博客搬至CSDN
- HDU 4549 (费马小定理+矩阵快速幂+二分快速幂)