C语言socket编程总结(七)int socket/connect()/send()/recv()/close()/shutdown()/recvfrom

    //1.创建socket

    /*

     int socket(int domain, int type, int protocol);

     1.协议族 ipv4或者其他的ip协议.

     2.type 指定传输层使用TCP或者 UDP (TCP SOCK_STREAM) (UDP SOCK_DGRAM数据报文)

     3.protocol指定传输层使用的协议

     返回值 大于0 创建socket成功

     */

    int clientSocket =socket(AF_INET,SOCK_STREAM, IPPROTO_TCP);

    NSLog(@"%d",clientSocket);

    

    //2.建立连接

    /*

     1.socket

     2.const struct sockaddr * 指定对方服务器的ip地址和端口号等信息结构体

     struct sockaddr_in addr;

     addr.sin_family = AF_INET;

     addr.sin_port=htons(PORT);

     addr.sin_addr.s_addr = inet_addr(SERVER_IP);

     sockaddr_in sockaddr更加容易看的明白,可以类型转换

     3.结构体的字节长度

     

     返回值: 0 成功 0 失败

     */

    struct sockaddr_in addr;

    //指定协议族 ipv4

    addr.sin_family = AF_INET;

    //端口号,htons高地位转换

    addr.sin_port = htons(12345);

    //12345-->0x3039-->0x3930-->14640

//    NSLog(@"%d",htons(12345));

    //指定IP地址,inet_addr把字符串转换成网络地址(数字)

    addr.sin_addr.s_addr =inet_addr("127.0.0.1");

    

   int connResult = connect(clientSocket, (const struct sockaddr *)&addr, sizeof(addr));

    

    //本地开启服务器终端 (netcat)  nc -lk 12345

    if(connResult == 0){

        NSLog(@"ok");

    }else{

        NSLog(@"fail");

    }

    

    //3.发送数据给服务器

    /*

     1.socket

     2.要发送的数据

     3.要发送数据的字节长度

     4.调用执行方式 flag是否阻塞,一般填0即可

     返回值:成功发送的字节数

     */

    

    char * str = "itcast";

    ssize_t sentLen = send(clientSocket, str, strlen(str), 0);

    //sizeof表示在内存中保存该变量需要多少字节 ,一个字节8

//    NSLog(@"%zd %lu %lu",sentLen,strlen(str),sizeof(str));

    

    //4.接受数据(从服务器接收数据)

    /*

     1.socket

     2.用于保存数据的缓存

     3.缓冲区的长度

     4.指定调用方式。一般填0即可

     返回值接收的字节长度

     */

    char *buffer[1024];

    ssize_t recvLen = recv(clientSocket, buffer, sizeof(buffer),0);

//    NSLog(@"---->%zd",recvLen);

    

    //输出字符串

    //二进制 NSData

    NSData *data = [NSDatadataWithBytes:buffer length:recvLen];

    //字符串输出

    NSString *string = [[NSStringalloc] initWithData:dataencoding:NSUTF8StringEncoding];

    

    NSLog(@"%@",string);

    

    //5.关闭数据

    //socket

    close(clientSocket);


===============

1.close()函数

[cpp]  view plain  copy
 print ?
  1. <span style="font-size:13px;">#include<unistd.h>  
  2. int close(int sockfd);     //返回成功为0,出错为-1.</span>  

    close 一个套接字的默认行为是把套接字标记为已关闭,然后立即返回到调用进程,该套接字描述符不能再由调用进程使用,也就是说它不能再作为read或write的第一个参数,然而TCP将尝试发送已排队等待发送到对端的任何数据,发送完毕后发生的是正常的TCP连接终止序列。

    在多进程并发服务器中,父子进程共享着套接字,套接字描述符引用计数记录着共享着的进程个数,当父进程或某一子进程close掉套接字时,描述符引用计数会相应的减一,当引用计数仍大于零时,这个close调用就不会引发TCP的四路握手断连过程。

2.shutdown()函数

[cpp]  view plain  copy
 print ?
  1. <span style="font-size:13px;">#include<sys/socket.h>  
  2. int shutdown(int sockfd,int howto);  //返回成功为0,出错为-1.</span>  

    该函数的行为依赖于howto的值

    1.SHUT_RD:值为0,关闭连接的读这一半。

    2.SHUT_WR:值为1,关闭连接的写这一半。

    3.SHUT_RDWR:值为2,连接的读和写都关闭。

    终止网络连接的通用方法是调用close函数。但使用shutdown能更好的控制断连过程(使用第二个参数)。

3.两函数的区别
    close与shutdown的区别主要表现在:
    close函数会关闭套接字ID,如果有其他的进程共享着这个套接字,那么它仍然是打开的,这个连接仍然可以用来读和写,并且有时候这是非常重要的 ,特别是对于多进程并发服务器来说。

    而shutdown会切断进程共享的套接字的所有连接,不管这个套接字的引用计数是否为零,那些试图读得进程将会接收到EOF标识,那些试图写的进程将会检测到SIGPIPE信号,同时可利用shutdown的第二个参数选择断连的方式。

使用close中止一 个连接,但它只是减少描述符的参考数,并不直接关闭连接,只有当描述符的参考数为0时才关闭连接。
shutdown可直接关闭描述符,不考虑描述 符的参考数,可选择中止一个方向的连接。

注意:
    1>. 如果有多个进程共享一个套接字,close每被调用一次,计数减1,直到计数为0时,也就是所用进程都调用了close,套接字将被释放。
    2>. 在多进程中如果一个进程中shutdown(sfd, SHUT_RDWR)后其它的进程将无法进行通信. 如果一个进程close(sfd)将不会影响到其它进程. 得自己理解引用计数的用法了

  recvfrom

ssize_t recvfrom(int sockfd,void *buf, size_t len, int flags,

struct sockaddr *src_addr, socklen_t *addrlen)

windows版本:

int recvfrom(IN SOCKET s, OUT char FAR * buf, IN int len, IN int flags, OUT struct sockaddr FAR * from,IN OUTint FAR * fromlen)

着重强调参数:

       sockfd:接收端套接字描述

       buf:用于接收数据的应用缓冲区地址

       len:指名缓冲区大小

       flags:通常为0

       src_addr:数据来源端的地址

       addrlen:src_addr地址的长度

注意后两个参数是输出参数,其中addrlen既是输入又是输出参数,即值-结果参数,需要在调用时,指明src_addr的长度。另外,如果不关心数据发送端的地址,可以将后两者均设置为NULL。

 




  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值