再学BSD Socket


最近要做ios的socket.看了看ios所有类似点对点通信的文档.bsd socket,cfsocket,cfnetwork,cfstream

今天写总结下bsd socket.由于以前做c++的时候,用过.

常用函数:

server:

socket(),bind(),listen(),accept(),read(),write()/recv(),send().

client:

socket(),connect(),read(),write()/recv(),send().


需要死循环的函数:

server:

accept(),read()/recv()

client:

read()/recv()


read write 区别 send recv

原文地址

 1)connect()+write()+read() [适用于TCP] 这是一个“古老”的I/O搭配了,“远在”无名管道的工作部分就已经有详细地记录了,不过在这里偶还是要 讲一下。write()+read()主要出现在管道I/O工作上,无论是有名管道还是无名管道,它们主要都是依靠writ e()+read()进行基本的数据通信的,这个搭配属于UNIX系统中非常低层的I/O系统调用了,而TCP开始设计时 就被当作是网络上传输管道数据的替代品,当然也就顺理成章地继承这个基本的I/O调用搭配了。
下面讲解的 write()+read()调用主要是以BSD Socket下的运用方式为主
 必须头: #include <sys/types.h> #include <sys/uio.h> #include <unistd.h> 
关于write() ssize_t write(int d,const void *buf,size_t nbytes); 调用成功返回成功写入的字节数,调用失败则返回-1。参数1为对象的句柄;参数2是写入的内容;参数3是前 者的大小。 
关于read() ssize_t read(int d,void *buf,size_t nbytes); 正常调用返回成功读入的字节数,当读到句柄对象的底部时返回0,调用失败返回-1。参数1为对象句柄;参 数2是读入容器的地址;参数3是前者的大小。

2)sendto()+recvfrom() [适用于TCP、UDP,多数用于UDP] 这是一个比较“游动”的I/O方式调用,仅适用于UDP传输(也是UDP的I/O调用的魅力所在),因为UDP本身的 特性(不需要三次握手),所以它需要一种非常灵活的传输模式,有了这个模式,服务端与客户端的模式就 没有一个很笼统的分化了(在范例中我们可以看出服务端与客户端在程序的编排上几乎是一致的,除了服务 端多了一个bind()调用与一个循环结构以外),程序设计者可以按照需求更巧妙地设计自己的程序。
 必须头: #include <sys/types.h> #include <sys/socket.h> 
关于sendto() ssize_t sendto(int s,const void *msg,size_t len,int flags,const struct sockaddr *to,socklen_t tolen); 调用成功返回成功写入的字节数,调用失败则返回-1。参数1是套接字句柄;参数2是需要发送的数据;参数3 是前者的大小;参数4是特殊传输标识,其值多为0;参数5是发送目的地的sockaddr结构主机地址的指针值; 参数6是前者的长度。 
关于recvfrom() ssize_t recvfrom(int s,void *buf,size_t len,int flags,struct sockaddr *from,socklen_t *fromlen ); 正常调用返回成功读入的字节数,调用失败返回-1。参数1是套接字句柄;参数2是成功接收到远程传输过来 后的数据时放入的变量地址;参数3是前者的大小;参数4是特殊传输标识,其值多为0;参数5是接收到的数 据的发送端的sockaddr结构主机地址的指针值;参数6是前者长度的地址值。 
/* 以前总以为sendto()+recvfrom()调用只能用于UDP传输,原来这个论点是错的,这里偶做了个小实验...服务 端用我在《BSD Socket在传输层中的应用范例(TCP)》一文中的服务端,而客户端是: #include<sys/socket.h> #include<sys/types.h> #include<netinet/in.h> int main(int argc,char *argv[]){ int sock; struct sockaddr_in addr; char msg[101]; bzero((char *)msg,101); if((sock=socket(AF_INET,SOCK_STREAM,0))==-1){ //这里用的是TCP printf("fail for socket./n"); exit(-1); } bzero((char *)&addr,sizeof(addr)); addr.sin_family=AF_INET; addr.sin_addr.s_addr=inet_addr(argv[1]); addr.sin_port=htons(atoi(argv[2])); printf("message:"); scanf("%100s",msg); if(sendto(sock,msg,sizeof(msg),0,(struct sockaddr *)&addr,sizeof(addr))){ //I/O这里我用了sendto()来代替send() printf("send is ok./n"); close(sock); exit(0); }else{ printf("send is fail./n"); close(sock); exit(-1); } } 上面我用了sendto()来代替send(),并去除开始时的connect()调用(根据UDP的调用模式),结果发现必须 运行两次服务端才能接收msg的数据,可见第一次sendto()代替connect()了,这样才能正常地运作。但如果 在前面一开始就调用connect()的话sendto()是可以完全代替send()的,不过因为sendto()多了两个参数,所 以相信还不会有人会这样调用的,这样的使用方法仅仅用于实验用途。 */

3)connect()+send()+recv() [适用于TCP、UDP,多数用于TCP] 因为connect()调用在前一篇文中已经介绍过了,所以我就不多说了,下面主要谈谈send()+recv()。在TCP的 I/O传输中它们可以完全地取代write()+read()(而且在功能上回更优胜一些,看它的最后一个调用参数就知 道了);在UDP则不能完全取代sendto()+recvfrom(),原因显而易见,因为send()+recv()少了“游动”地址 部分,所以如果在UDP中调用它们的话套接字根本就不知道应该发到哪里去,这也是为什么在UDP中要用conne ct()调用作为绑定了,又因为UDP不存在所谓的“三次握手”(需要发送连接请求),所以在UDP中我们可以 把“绑定”这种行为简单地归结为:bind()调用绑定本地地址,connect()调用绑定远程地址。 
必须头: #include <sys/types.h> #include <sys/socket.h> 
关于send() ssize_t send(int s, const void *msg, size_t len, int flags); 调用成功返回成功写入的字节数,调用失败则返回-1。参数1是套接字句柄;参数2是需要发送的数据;参数3 是前者的大小;参数4是特殊传输标识,其值多为0。 
关于recv() ssize_t recv(int s, void *buf, size_t len, int flags); 正常调用返回成功读入的字节数,调用失败返回-1。参数1是套接字句柄;参数2是成功接收到远程传输过来 后的数据时放入的变量地址;参数3是前者的大小;参数4是特殊传输标识,其值多为0。


  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值