欢迎来到得力文库 - 分享文档赚钱的网站! | 帮助中心 好文档才是您的得力助手!
得力文库 - 分享文档赚钱的网站
全部分类
  • 研究报告>
  • 管理文献>
  • 标准材料>
  • 技术资料>
  • 教育专区>
  • 应用文书>
  • 生活休闲>
  • 考试试题>
  • pptx模板>
  • 工商注册>
  • 期刊短文>
  • 图片设计>
  • ImageVerifierCode 换一换

    Socket 编程 参考.pdf

    • 资源ID:70014516       资源大小:220KB        全文页数:29页
    • 资源格式: PDF        下载积分:15金币
    快捷下载 游客一键下载
    会员登录下载
    微信登录下载
    三方登录下载: 微信开放平台登录   QQ登录  
    二维码
    微信扫一扫登录
    下载资源需要15金币
    邮箱/手机:
    温馨提示:
    快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。
    如填写123,账号就是123,密码也是123。
    支付方式: 支付宝    微信支付   
    验证码:   换一换

     
    账号:
    密码:
    验证码:   换一换
      忘记密码?
        
    友情提示
    2、PDF文件下载后,可能会被浏览器默认打开,此种情况可以点击浏览器菜单,保存网页到桌面,就可以正常下载了。
    3、本站不支持迅雷下载,请使用电脑自带的IE浏览器,或者360浏览器、谷歌浏览器下载即可。
    4、本站资源下载后的文档和图纸-无水印,预览文档经过压缩,下载后原文更清晰。
    5、试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。

    Socket 编程 参考.pdf

    Socket 编程 Socket 编程 参考 UNP 第一卷 chinaunix 论坛 一、基本知识 一、基本知识 主机字节序和网络字节序 主机字节序和网络字节序 主机字节序即内存中存储字节的方法有:1 Little endian:将低序字节存储在起始地址 2 Big endian:将高序字节存储在起始地址 网络字序表示网络协议在处理多字节时的顺序,一律为 big endian 主机字节序和网络字节序转换的函数:#include uint16_t htons(uint16_t)uint32_t htonsl(uint32_t)/转换为网络字节序 uint16_t ntohs(uint16_t)uint32_t ntohl(uint32_t)/转换为主机字节序 缓冲区 缓冲区 每个 TCP SOCKET 有一个发送缓冲区和一个接收缓冲区,TCP 具有流量控制,所以接收缓冲区的大小就是通知另一端的窗口的大小,对方不会发大于该窗口大小的数据;而 UDP SOCKET 只有一个接收缓冲区无流量控制,当接收的数据报溢出时就会被丢弃 通信域(地址族)通信域(地址族)套接字存在于特定的通信域(即地址族)中,只有隶属于同一地址族的套接字才能建立对话。Linux 支持 AF_INET(IPv4 协议)、AF_INET6(IPv6 协议)和 AF_LOCAL(Unix 域协议)。套接口(socket)网络地址+端口号。,要建立一个套接口必须调用 socket 函数,套接口有三种类型,即字节流套接口(SOCK_STREAM),数据报套接口(SOCK_DGRAM)和原始套接口(SOCK_RAW)。定义一个连接的一个端点的两元组,即 IP 地址和端口号,称为一个套接口。在网络连接中,两个端点所组成的四元组(即本地 IP、本地 PORT、远程 IP 和远程 PORT)称为 socket pair,该四元组唯一的标识了一个网络连接。该情况可通过 netstat 验证。二、socket 地址结构 1二、socket 地址结构 1 IPv4 的 Socket 地址结构(定长)IPv4 的 Socket 地址结构(定长)Struct in_addr In_addr_t s_addr;/32 位 IP 地址,网络字节序 Struct sockaddr_in Uint8_t sin_len;/IPv4 为固定的 16 字节长度 Sa_family_t sin_family;/地址簇类型,为 AF_INET In_port_t sin_port;/16 位端口号,网络字节序 Struct in_addr sin_addr;/32 位 IP 地址 Char sin_zero8;/未用 22 IPv6 的 socket 地址结构(定长)IPv6 的 socket 地址结构(定长)struct in6_addr uint8_t s6_addr16;/128 位 IP 地址,网络字节序 struct sockaddr_in6 uint8_t sin6_len;/IPv6 为固定的 24 字节长度 sa_family_t sin6_family;/地址簇类型,为 AF_INET6 in_port_t sin6_port;/16 位端口号,网络字节序 uint32_t sin6_flowinfo;/32 位流标签 struct in6_addr sin6_addr;/128 位 IP 地址 3 3 UNIX 域 socket 地址结构(变长)UNIX 域 socket 地址结构(变长)Struct sockaddr_un,地址簇类型为 AF_LOCAL 4 4 数据链路 socket 地址结构(变长)数据链路 socket 地址结构(变长)struct sockaddr_dl,地址簇类型为 AF_LINK 5 5 通用的 socket 地址结构 通用的 socket 地址结构 struct sockaddr uint8_t sa_len;sa_family_t sa_family;char sa_data14;三、C/S 网络编程 三、C/S 网络编程 初始化 sock 连接符:int socket(int domain,int type,int protocol);函数返回 socket 描述符,返回-1 表示出错 domain 参数只能取 AF_INET,protocol 参数一般取 0 应用示例:TCP 方式:sockfd=socket(AF_INET,SOCK_STREAM,0);UDP 方式:sockfd=socket(AF_INET,SOCK_DGRAM,0);绑定端口:int bind(int sockfd,struct sockaddr*sa,int addrlen);函数返回-1 表示出错,最常见的错误是该端口已经被其他程序绑定。需要注意的一点:在 Linux 系统中,1024 以下的端口只有拥有 root 权限的程序才能绑定。连接网络(用于 TCP 方式):int connect(int sockfd,struct sockaddr*servaddr,int addrlen);函数返回-1 表示出错,可能是连接超时或无法访问。返回 0 表示连接成功,可以通过 sockfd 传输数据了。监听端口(用于 TCP 方式):int listen(int sockfd,int queue_length);需要在此前调用 bind()函数将 sockfd 绑定到一个端口上,否则由系统指定一个随机的端口。接收队列:一个新的 Client 的连接请求先被放在接收队列中,直到 Server 程序调用 accept 函数接受连接请求。第二个参数 queue_length,指的就是接收队列的长度 也就是在 Server 程序调用 accept 函数之前最大允许的连接请求数,多余的连接请求将被拒绝。响应连接请求(用于 TCP 方式):int accept(int sockfd,struct sockaddr*addr,int*addrlen);accept()函数将响应连接请求,建立连接并产生一个新的 socket 描述符来描述该连接,该连接用来与特定的 Client 交换信息。函数返回新的连接的 socket 描述符,错误返回-1 addr 将在函数调用后被填入连接对方的地址信息,如对方的 IP、端口等。addrlen 作为参数表示 addr 内存区的大小,在函数返回后将被填入返回的 addr 结构的大小。accept 缺省是阻塞函数,阻塞直到有连接请求 应用示例:struct sockaddr_in their_addr;/*用于存储连接对方的地址信息*/int sin_size=sizeof(struct sockaddr_in);(依次调用 socket(),bind(),listen()等函数)new_fd=accept(sockfd,&their_addr,&sin_size);printf(”对方地址:%sn,inet_ntoa(their_addr.sin_addr);关闭 socket 连接:int close(int sockfd);关闭连接将中断对该 socket 的读写操作。关闭用于 listen()的 socket 描述符将禁止其他 Client 的连接请求。部分关闭 socket 连接:int shutdown(int sockfd,int how);Shutdown()函数可以单方面的中断连接,即禁止某个方向的信息传递。参数 how:0-禁止接收信息 1-禁止发送信息 2-接收和发送都被禁止,与 close()函数效果相同 socket 轮询选择:int select(int numfds,fd_set*readfds,fd_set*writefds,fd_set*exceptfds,struct timeval*timeout);应用于多路同步 I/O 模式(将在同步工作模式中详细讲解)FD_ZERO(*set)清空 socket 集合 FD_SET(s,*set)将 s 加入 socket 集合 FD_CLR(s,*set)从 socket 集合去掉 s FD_ISSET(s,*set)判断 s 是否在 socket 集合中 常数 FD_SETSIZE:集合元素的最多个数 等待选择机制:int poll(struct pollfd*ufds,unsigned int nfds,int timeout);是 select 机制的一个变种,应用于多路同步 I/O 模式(将在同步工作模式中详细讲解)ufds 是 pollfd 结构的数组,数组元素个数为 nfds。struct pollfd int fd;/*文件描述字*/short events;/*请求事件集合*/short revents;/*返回时间集合*/;接收/发送消息:TCP 方式:int send(int s,const void*buf,int len,int flags);int recv(int s,void*buf,int len,int flags);函数返回实际发送/接收的字节数,返回-1 表示出错,需要关闭此连接。函数缺省是阻塞函数,直到发送/接收完毕或出错 注意:如果 send 函数返回值与参数 len 不相等,则剩余的未发送信息需要再次发送 UDP 方式:int sendto(int s,const void*buf,int len,int flags,const struct sockaddr*to,int tolen);int recvfrom(int s,void*buf,int len,int flags,struct sockaddr*from,int*fromlen);与 TCP 方式的区别:需要指定发送/接收数据的对方(第五个参数 to/from)函数返回实际发送/接收的字节数,返回-1 表示出错。函数缺省是阻塞函数,直到发送/接收完毕或出错 注意:如果 send 函数返回值与参数 len 不相等,则剩余的未发送信息需要再次发送 注意,网络字节流的读写不同于文件的读写,由于 socket 缓冲的因素,可能读写的字节数小于所指定的字节数。所以可以使用如下函数:ssize_t readn(int fd,void*buf,size_t n)ssize_t nleft;ssize_t nread;char*ptr;ptr=buf;nleft=n;while(nleft 0)if(nread=read(fd,ptr,nleft)0)if(nwrite=write(fd,ptr,left)=0)if(errno=EINTR)nwrite=0;else return(-1);nleft-=nwrite;ptr+=nwrite;return(n);基于消息的方式:int sendmsg(int s,const struct msghdr*msg,int flags);int recvmsg(int s,struct msghdr*msg,int flags);标志位:上面这六个发送/接收函数均有一个参数 flags,用来指明数据发送/接收的标志,常用的标志主要有:MSG_PEEK 对数据接收函数有效,表示读出网络数据后不清除已读的数据 MSG_WAITALL 对数据接收函数有效,表示一直执行直到 buf 读满、socket 出错或者程序收到信号。MSG_DONTWAIT 对数据发送函数有效,表示不阻塞等待数据发送完后返回,而是直接返回。(只对非阻塞 socket 有效)MSG_NOSIGNAL 对发送接收函数有效,表示在对方关闭连接后出错但不发送 SIGPIPE 信号给程序。MSG_OOB 对发送接收都有效,表示读/写带外数据(out-of-band data)IP 地址字符串和网络字节序的二进制 IP 地址相互转换的函数:IP 地址字符串和网络字节序的二进制 IP 地址相互转换的函数:#inlcude int inet_aton(const char*,struct in_addr*)成功1 失败0 通用地址函数int inet_pton(int,可以是 AF_INET/AF_INET6,const char*,void*)成功1 格式错误0 失败0 in_addr_t inet_addr(const char*)返回 32 位网络字节序的 IP 地址,失败INADDR_NONE char*inet_ntoa(struct in_addr)返回 IP 地址字符串 const char*inet_ntop(int,const void*,char*,size_t )返回指向结果的指针 字节顺序转换 htons()-Host to Network Short htonl()-Host to Network Long ntohs()-Network to Host Short ntohl()-Network to Host Long 连接过程是通过一系列状态表示的,这些状态有:LISTEN,SYN-SENT,SYN-RECEIVED,ESTABLISHED,FIN-WAIT-1,FIN-WAIT-2,CLOSE-WAIT,CLOSING,LAST-ACK,TIME-WAIT 和 CLOSED。CLOSED 表示没有连接,各个状态的意义如下:LISTEN-侦听来自远方 TCP 端口的连接请求;SYN-SENT-在发送连接请求后等待匹配的连接请求;SYN-RECEIVED-在收到和发送一个连接请求后等待对连接请求的确认;ESTABLISHED-代表一个打开的连接,数据可以传送给用户;FIN-WAIT-1-等待远程 TCP 的连接中断请求,或先前的连接中断请求的确认;FIN-WAIT-2-从远程 TCP 等待连接中断请求;CLOSE-WAIT-等待从本地用户发来的连接中断请求;CLOSING-等待远程 TCP 对连接中断的确认;LAST-ACK-等待原来发向远程 TCP 的连接中断请求的确认;TIME-WAIT-等待足够的时间以确保远程 TCP 接收到连接中断请求的确认;CLOSED-没有任何连接状态;Tcp 面向连接 如下图所示:Socket()Server(主动打开)Bind()Listen()Accept()Socket()Client(被动打开)Connect()Write()Read()Read()Write()Close()Read()Close()#include int socket(int,int,int protocol)非负整数表示socket描述字-成功-1-失败#include int connect(int socket描述 字 ,c o n s t s t r u c ts o c k a d d r *服 务 器 的SOCKET地址,socklen_t 服务器的SOCKET地址结构长度)0成功1失败#include int bind(int,const structsockaddr*,socklen_t)0-成功1-失败若SOCKET地址中:IP地址为通配地址INADDR_ANY(0),或PORT为0,都表示为让内核选择#include int listen(int,int)成功-1-出错3进入未完成连接队列中,SYN_RCVD状态4转入已完成队列队列中,ESTABLISHED状态#include int accept(int,structsockaddr*,socklen_t*)非负描述字(已连接套接口)-成功-1-出错2SYN_SENT状态1CLOSED状态3ESTABLISHED状态4FIN_WAIT1状态5FIN_WAIT2状态6TIME_WAIT状态7CLOSED状态TIMEOUT=2MSL(max segementlifetime 1-4分钟)1CLOSED状态2LISTEN状态5CLOSED_WAIT6LAST_ACK7CLOSED TIME_WAIT 状态 一个 tcp 协议的 socket 编程例子:Server Server/*主函数*/int listenfd,connfd;struct sockaddr_in servaddr,cliaddr;struct hostent*hp;struct servent*sp;struct in_addr*pptr;if(hp=gethostbyname(argv1)=NULL)/error if(sp=getservbyname(argv2,“tcp”)=NULL)/error pptr=(struct in_addr*)hp-h_addr_list;listenfd=socket(AF_INET,SOCK_STREAM,0);bzero(&servaddr,sizeof(servaddr);servaddr.sin_family=AF_INET;/servaddr.sin_addr.s_addr=htonl(INADDR_ANY);memcpy(&servaddr.sin_addr,*pptr,sizeof(struct in_addr);servaddr.sin_port=htons(portnum);bind(listenfd,(struct sockaddr*)&servaddr,sizeof(servaddr);listen(listenfd,listenqueuenum);signal(SIGCHLD,sig_chld);for(;)len=sizeof(cliaddr);if(connfd=accept(listenfd,(struct sockaddr*)&cliaddr,&len)0);return;client client sockfd=socket(AF_INET,SOCK_STREAM,0);bzero(&servaddr,sizeof(servaddr);bzero(&servaddr,sizeof(servaddr);servaddr.sin_familf=AF_INET;servaddr.sin_port=htons(SERV_PORT);inet_pton(AF_INET,SERV_IP_STRING,&servaddr.sin_addr);connect(sockfd,(struct sockaddr*)&serv_addr,sizeof(servaddr);./process exit(0);终止网络连接的正常方法是调用 close(),但是有两个限制:1 将描述字的访问计数-1,到 0 时才激发 TCP 连接的终止序列(丢弃接收缓冲区里的数据,发送发送缓冲区里的数据,如果描述字的访问计数为 0,在数据之后发出 FIN)2 终止了数据传输的两个方向,读和写 shutdown 可以关闭一半连接,而且在发完发送缓冲区里的数据后立即发出 FIN 序列 UDP 无连接 编程时,在 SERVER 端少了 accept()和 listen(),客户端少了 connect(),因为是无连接的,所以不用 close(),读写一般用 sendto()和 recvfrom()。如果 client 发送的数据被路由丢弃或者服务器的应答信息丢失,那么 client 将一直阻塞,直到应用设置的超时到达,UDP 需要应用来做接受确认、传输超时或者重传的机制。一般的,UDP 服务属于迭代的,而 TCP 服务大多数是并发的。用 I/O 复用方式(select())实现(可以避免为每个客户端连接创建一个进程的开销):server server int clientFD_SETSIZE;fd_set allset,rset;maxfd=listenfd;maxi=-1;for(I=0;I FD_SETSIZE;i+)clienti=-1;FD_ZERO(&allset);FD_SET(listenfd,&allset);For(;)rset=allset;nready=select(maxfd+1,&rset,NULL,NULL,NULL);if(FD_ISSET(listenfd,&rset)/新连接 clilen=sizeof(cliaddr);connfd=accept(listenfd,(struct sockaddr*)&cliaddr,&clilen);for(i=0;I FD_SETSIZE;i+)if(clienti maxfd)Maxfd=connfd;If(I maxi)Maxi=I;If(-nready=0)Continue;for(I=0;I=maxi;i+)if(sockfd=clienti)0)continue;if(FD_ISSET(sockfd,&rset)if(n=read(sockfd,)=0)/客户端已经关闭连接 close(sockfd);FD_CLR(sockfd,&allset);Clienti=-1;else /process if(-nready=0)break;用这种方法有一个问题:容易受 DDOS 攻击。如一个客户端发一个字节,就睡眠,该程序将阻塞在 read()上,无法再为其他合法的客户端服务。解决方法:1 非阻塞 I/O 2 为每个连接创建进程或线程 3 对 I/O 操作设置操时 四、常用函数 四、常用函数 函数中均使用通用地址结构,所以一般要将特定协议的地址转换成通用地址结构。1从进程到内核 bind connect sendto sendmsg 2从内核到进程 Accept Recvfrom Recvmsg Getpeername Getsockname 3.解析器函数:ethostbyname gethostbyaddr getservbyname 端口号是以网络字节序返回的 getservbyport 参数 port 必须是网络字节序,所以要调用 htons(port num)4I/O 流和描述字 fdopen():将描述字(int)转换为 I/O 流(FILE*)fileno():将 I/O 流转换为描述字 注 意:虽 然 一 个 I/O 流 也 是 全 双 工 的,但 是 读 和 写 之 间 必 须 要 有 一 些 如fflush(),fseek(),fsetpos(),rewind()函数。最好的办法是对一个描述字创建两个流,读和写分开。FILE*fin,*fout;Fin=fdopen(sockfd,“r);Fout=fdopen(sockfd,“w”);Fgets();Fputs();但是这种标准 I/O 库的编程必须注意当前的缓冲方式:完全缓冲:只有缓冲区满、fflush()或进程 exit()时才输出 I/O 行缓冲 不缓冲 五、僵尸进程 五、僵尸进程 Zombie进程:一个子进程终止,系统内核会发出 SIGCHLD 信号,如果程序中没有用 singal、sigaction 进行 SIG_IGN 处理,也没有用 wait、waitpid 进行等待,结束的子进程就会变为僵尸进程。僵尸进程产生的目的是保存子进程的信息,以便父进程在以后某个时刻需要取回 如果一个进程终止,但子进程有 Zombie 状态,这时他们的父进程将由 pid=1 的 init 进程接管,用 wait 来等待负责收回僵尸进程的资源。僵尸进程占用内核空间,六、I/O 模式 六、I/O 模式 5 个 I/O 模式:1 阻塞 I/O 2 非阻塞 I/O 设置该标志代码:int flags;if(flags=fcntl(fd,F_GETFL,0)0)/出错处理 flags|=O_NONBLOCK;if(fcntl(fd,F_SETFL,flags)0)/出错处理 关闭该标志代码:flags&=O_NONBLOCK;非阻塞 connect 的典型应用:/设置 sockfd 为非阻塞,如上述代码 if(n=connect()0)if(errno!=EINPROCESS)/正常情况下,connect 连接有一定时间,应该返回EINPROCESS return(-1);if(n=0)/特殊情况,如 CLIENT 和 SERVER 在同台主机上,连接快速返回 goto done;FD_ZERO(&rset);FD_SET(sockfd&rset);West=rset;Struct timeval val;Val.tv_sec=;Val.tv_usec=0;If(n=select(sockfd+1,&rset,&west,NULL,&val)=0)/超时 Errno=ETIMEOUT;Close(sockfd);Return(-1);int error;if(FD_ISSET(sockfd,&rset)|FD_ISSET(sockfd,&west)len=sizeof(error);if(getsockopt(sockfd,SOL_SOCKET,SO_ERROR,&error,&len)0)/检查 SOCKET上待处理的错误 return(-1);else /出错处理,表示在这段时间内没连接上 SERVER done:fcntl(sockfd,FD_SETFL,flags);/恢复为原来的模式 if(error)close(sockfd);errno=error;return(-1);return(0);3 I/O 复用 4 信号驱动 I/O(SIGIO)5 异步 I/O 前 4 个 I/O 模式都属于同步 I/O,因为它们都阻塞于 I/O 的操作(即 I/O 数据准备好时,从内核空间往用户空间拷贝数据)七、守护进程 七、守护进程 在后台运行并且与终端脱离联系的进程,只要系统不停止就一直运行着。有几种方式启动:1/etc/rcx.d 下的启动脚本 2Inetd 启动 3Cron 或者 at 启动 守护进程的输出信息一般通过 SYSLOG 输出 函数示例:#include#define MAXFD 64 void daemon_init()int I;pid_t pid;if(pid=fork()!=0)exit(0);setsid():signal(SIGHUP,SIG_IGN):if(Pid=fork()!=0)exit(0):chdir(“/”);umask(0);for(i=0;iMAXFD;i+)close(i);openlog(logname,LOG_PID,facility);八、I/O 超时 八、I/O 超时 方法 1:alarm()例如:static void connect_alarm(int signo)return;signal(SIGALARM,connect_alarm);if(alarm(timeout_sec)!=0)/error if(connect(sockfd,(struct sockaddr*)servaddr,servlen)0)close(sockfd);if(errno=EINTR)errno=ETIMEDOUT;alarm(0);方法 2:select()例如:int readable_timeout(int fd,int sec)fd_set rset;struct timeval tv;FD_ZERO(&rset);FD_SET(fd,&rset):Tv.tv_sec=sec;Tv.tv_usec=0;Return(select(fd+1,&rset,NULL,NULL,&tv);sendto(sockfd,);if(readable_timeout(sockfd,5)=0)/error else recvfrom(sockfd,);/可以读 方法 3:SO_RCVTIMEO 和 SO_SNDTIMEO 套接口选项 例如:struct timeval tv;tv.tv_sec=5;tv.tv_usec=0;setsockopt(sockfd,SOL_SOCKET,SO_RCVTIMEO,&tv,sizeof(tv):while(fgets(sendline)!=NULL)sendto(sockfd,);n=recvfrom(sockfd,);if(n0)if(errno=EWOULEBLOCK)fprintf(stderr,“socket,timeout”);continue;else /error;九、辅助数据的应用 可以运用于任何进程之间传递描述字的应用 九、辅助数据的应用 可以运用于任何进程之间传递描述字的应用 sendmsg 和 recvmsg 可以用来传送辅助数据(控制信息)。辅助数据由若干个辅助对象组成,每个辅助对象由一个 cmsghdr 结构开头。struct msghdr void *msg_name;/用于 UDP 协议,发送方可以存放目的地址,接收方可以存放发送地址 size_t msg_namelen;/同上 struct iovec*msg_iov;/输入输出缓冲区数据,两个成员iov_base 和 iov_len int msg_iovlen;void *msg_control;/辅助数据 size_t msg_controllen;/辅助数据大小 int msg_flags;/只对 recvmsg 有用;Struct cmsghdr Socklen_t cmsg_len;Int cmsg_level;/IPV4 是 IPPROTO_IP,UNIX 域是 SOL_SOCKET Int Cmsg_type;/在 IPV4 中,IP_RECVDSTADDR 接受 UDP 数据报的目的地址 /IP_RECVIF 接受 UDP 数据报的接口索引 /UNIX 域中是 SCM_RIGHTS 传送描述字 /SCM_CREDS 传送用户凭证 /char cmsg_data;msghdr.msg_control 指向的辅助数据必须按 cmsghdr 结构对齐。利用 UNIX 域 SOCKET 方式:my_open(const char*pathname,int mode)int sockfd2;socketpair(AF_LOCAL,SOCK_STREAM,0,sockfd);/创建了一个流管道 if(childpid=fork()=0)/子进程 close(socdfd0);snprintf(argsockfd,sizeof(argsocdfd),“%d”,sockfd1);snprintf(argmode,sizeof(mode),“%d”,mode);execl(“./openfile”,“openfile”,argsockfd,pathname,argmode,(char*)NULL);perror(“exec errorn”);close(sockfd1);waitpid(chidpid,&status,0);if(WIFEXITED(status)=0)perror(“chid process did not terminaten”);if(status=WEXITSTATUS(status)=0)/把终止状态转换为退出状态 0-255 read_fd(sockfd0,&c,1,&fd);else errno=status;fd=-1;close(sockdf0);return(fd);ssize_t read_fd(int fd,void*ptr,ssize_t nbytes,int*recvfd)struct msghdr msg;/辅助数据对象 struct iovec iov1;union struct cmsghdr unit;/这里定义辅助数据对象的目的是为了让 msg_control 缓冲区和辅助数据单元对齐,所以不是简单地定义一个char control,而是定义一个union char controlCMSG_SPACE(sizeof(int);/辅助数据缓冲区 control_buf;struct cmsghdr*unitptr;int n;msg.msg_control=control_buf.control;/辅助数据缓冲区 msg.msg_controllen=sizeof(control_buf.control);/辅助数据大小 msg.msg_name=NULL;msg.msg_namelen=0;iov0.iov_base=ptr;iov0.iov_len=nbytes;msg.msg_iov=iov;msg.msg_iovlen=1;if(n=recvmsg(fd,&msg,0)cmsg_len=CMSG_LEN(sizeof(int)/cmsg_len 应该=CMSG_LEN 宏得出的结果 if(unitptr-cmsg_level!=SOL_SOCKET)/UNIX DOMAIN 用 SOL-SOCKET /error if(unitptr-cmsg_type!=SCM_RIGHTS)/error *recvd=*(int*)CMSG_DATA(unitptr);/获得该辅助对象的数据 else *recvd=-1;return(n);子进程写程序摘录:msg.msg_control=control_buf.control;msg.msg_controllen=sizeof(control_buf.control);unitprt=CMSG_FIRSTHDR(&msg);unitptr-cmsg_len=CMSG_LEN(sizeof(int);unitptr-cmsg_level=SOL_SOCKET;unitptr-cmsg_level=SCM_RIGHTS;*(int*)CMSG_DATA(unitptr)=sendfd;/CMSG_DATA()返回与 cmsghdr 相关联的数据的第一个字节的指针 msg.msg_name=NULL;msg.msg_namelen=0;iov0.iov_base=ptr;iov0.iov_len=nbytes;msg.msg_iov=iov;msg.msg_iovlen=1;sendmsg(fd,&msg,0);用户凭证#用户凭证#include struct fcred uid_t fc_ruid;/真实 UID gid_t fc_rgid;/真实 GID char fc_loginMAXLOGNAME;/LOGIN 名字 uid_t fc_uid;/有效 UID short fc_ngroups;/组数 gid_t fc_groupsNGROUPS;#define fc_gid fc_groups0;/有效 GID 需要将 LOCAL _CREDS 这个 SOCKET 选项设置为 1,在 TCP 中是 CLIENT 在连接后第一次发送数据时由内核一起发送的,UDP 是每次发送数据都产生 十、网络参数的设置和获取 十、网络参数的设置和获取 获得主机名存到 hostname 中 int gethostname(char*hostname,size_t size);取得本地的 SOCKET 信息 int getsockname(int sockfd,struct sockaddr*addr,int*addrlen);取得对方主机的 SOCKET 信息 int getpeername(int sockfd,struct sockaddr*addr,int*addrlen);获得 DNS 信息:struct hostent*gethostbyname(const char*name);struct hostent*gethostbyaddr(const char*addr,int len,int type);返回了一个指向 struct hostent 的指针,struct hostent 定义如下:struct hostent char*h_name;/*主机域名*/char*h_aliases;/*别名*/int

    注意事项

    本文(Socket 编程 参考.pdf)为本站会员(qwe****56)主动上传,得力文库 - 分享文档赚钱的网站仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知得力文库 - 分享文档赚钱的网站(点击联系客服),我们立即给予删除!

    温馨提示:如果因为网速或其他原因下载失败请重新下载,重复下载不扣分。




    关于得利文库 - 版权申诉 - 用户使用规则 - 积分规则 - 联系我们

    本站为文档C TO C交易模式,本站只提供存储空间、用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。本站仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知得利文库网,我们立即给予删除!客服QQ:136780468 微信:18945177775 电话:18904686070

    工信部备案号:黑ICP备15003705号-8 |  经营许可证:黑B2-20190332号 |   黑公网安备:91230400333293403D

    © 2020-2023 www.deliwenku.com 得利文库. All Rights Reserved 黑龙江转换宝科技有限公司 

    黑龙江省互联网违法和不良信息举报
    举报电话:0468-3380021 邮箱:hgswwxb@163.com  

    收起
    展开