socket 通信

本文介绍了套接字编程中read函数的工作原理,强调了在阻塞模式下设置MSG_WAITALL标志以确保接收定长数据的重要性。同时,探讨了实现非阻塞模式的两种方法,即通过fcntl修改套接字选项和使用MSG_DONTWAIT标志。文中还提供了一个简单的服务器和客户端示例代码,展示了这两种模式的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

几个需要注意的点:read函数阻塞下并不是如想象一般 读取等到满足相应的长度再退出,而是一收到数据就会返回;

想要达到 接收定长数据的效果,需要在阻塞模式下 将flags 置为:MSG_WAITALL;

实现 非阻塞的模式,有两种 方式:

一种是在connect和accept过后进行 1.获取套接字的相关字段,并进行修改,大致如下:

int x; x=fcntl(s,F_GETFL,0); fcntl(s,F_SETFL,x | O_NONBLOCK);

 

另外一种方法是:将send/recv 的flags置为 :MSG_DOTWAIT

参考:

https://blog.csdn.net/kai8wei/article/details/77479240?ops_request_misc=&request_id=&biz_id=102&utm_term=MSG_DONTWAIT&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-0-77479240.first_rank_v2_pc_rank_v29

 

自己写得demo:

#server.c

#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <string.h>

#define PORT 8888

int main()
{
    int servSock = 0;
    struct sockaddr_in  clntAddr;
    socklen_t clntAddrSize = sizeof(clntAddr);           //socklen_t==int 
    int clntSock;

    if((servSock = socket(AF_INET,SOCK_STREAM,0)) == -1)                           // creat socket
    {
        printf("socket create failure!\n");
        exit(1);
    }
    else
    {   
        printf("socket create success!\n");
    }
    struct sockaddr_in servAddr;
    memset(&servAddr,0,sizeof(servAddr));
    servAddr.sin_family = AF_INET;                                                   //IPV4
    servAddr.sin_addr.s_addr = inet_addr("127.0.0.1");                             //IP addr:str--->struct
    servAddr.sin_port = htons(PORT);                                                  //port format transform
    if(bind(servSock, (struct sockaddr *)&servAddr, sizeof(servAddr)) !=0)
    {
        printf("bind  failure!\n");
        exit(2);
    }
    else
    {
        printf("bind success!\n");
    }
        
    if(listen(servSock, 10) != 0)
    {
        printf("listen failure!\n");
        exit(3);
    }
    else
    {
        printf("listen...\n");
    }
    
    clntSock = accept(servSock, (struct sockaddr*)&clntAddr, &clntAddrSize);  //阻塞 clntSock;
    if(clntSock <= 0)
    {
        printf("accept failure!\n");
        sleep(1);
    }
    else
    {
        printf("accept sucess!\n");
        char * msgRcv = (char *)malloc(sizeof(char)*300);
        while(1)
        {
             int n = recv(clntSock,msgRcv,300,MSG_WAITALL);                      
            if(n > 0)
            {
                //printf("%s,%ld \n",msgRcv,strlen(msgRcv));
                printf("%d \n",n);
                memset(msgRcv,0,300);
            }
            else
            {
                printf("received nothing!\n");
                sleep(1);
                //break;
            }
        }
    free(msgRcv);
    }
    close(clntSock);
    close(servSock);
    return 0;
}

#################################################################

#client.c

#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <stdint.h>
#define PORT 8888

 int main()
{
    uint32_t msg[] = {0x01,0x01,0x01,0x01,0x99,0x01,0x01,0x01,0x21,0x41,0x31,0x11,0x01,0x01,0x01,0x01,0x99,0x01,0x01,0x01,0x21,0x41,0x31,0x11,
        0x01,0x01,0x01,0x01,0x99,0x01,0x01,0x01,0x21,0x41,0x31,0x11,0x01,0x01,0x01,0x01,0x99,0x01,0x01,0x01,0x21,0x41,0x31,0x11,0x01,0x21,0x01,0x01,0x99,0x01,0x01,0x01,0x21,0x41,0x31,0x11,
        0x82,0x01,0x01,0x01,0x21,0x41,0x31,0x11,
        0x01,0x01,0x01,0x01,0x99,0x01,0x01,0x01,0x21,0x41,0x31,0x11,0x01,0x01,0x01,0x01,0x99,0x01,0x01,0x01,0x21,0x41,0x31,0x11,0x01,0x21,0x01,0x01,0x99,0x01,0x01,0x01,0x21,0x41,0x31,0x11,0x01,0x01,0x01,0x01,0x99,0x01,0x01,0x01,0x21,0x41,0x31,0x11,0x01,0x01,0x01,0x01,0x99,0x01,0x01,0x01,0x21,0x41,0x31,0x11,
        0x01,0x01,0x01,0x01,0x99,0x01,0x01,0x01,0x21,0x41,0x31,0x11,0x01,0x01,0x01,0x01,0x99,0x01,0x01,0x01,0x21,0x41,0x31,0x11,0x01,0x21,0x01,0x01,0x99,0x01,0x01,0x01,0x21,0x41,0x31,0x11,
        0x82,0x01,0x01,0x01,0x21,0x41,0x31,0x11,
        0x01,0x01,0x01,0x01,0x99,0x01,0x01,0x01,0x21,0x41,0x31,0x11,0x01,0x01,0x01,0x01,0x99,0x01,0x01,0x01,0x21,0x41,0x31,0x11,0x01,0x21,0x01,0x01,0x99,0x01,0x01,0x01,0x21,0x41,0x31,0x11};
    char * msgBear =(char*) msg;
    
    int clntSock=socket(AF_INET,SOCK_STREAM,0);
    struct sockaddr_in serv_addr;
    //server IP configuaration 
    memset(&serv_addr,0,sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
    serv_addr.sin_port = htons(PORT);
    int len = 0;

    int ret = connect(clntSock,(struct sockaddr *)&serv_addr,sizeof(serv_addr));
    if(ret < 0)
    {
        printf("ret = %d,connect error!\n",ret);
    }
    else
    {
        while(1)
            {
                int n = send(clntSock,msgBear,20,MSG_DONTWAIT);
                if(n > 0)
                {
                    printf("send bytes %d\n",n);
                    sleep(1);
                }
                else
                {
                    printf("send failure!\n");
                    sleep(1);
                    //break;
                }

            }
    }
    close(clntSock); 
    return 0;
     }


 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值