国嵌实时监控系统代码笔记(三)采集端 net.c

来源:互联网 发布:自动打印软件 编辑:程序博客网 时间:2024/06/07 16:19

intPASCALFARrecv(SOCKETs,charFAR*buf,intlen,intflags);

(1)recv先等待s的发送缓冲中的数据被协议传送完毕,如果协议在传送s的发送缓冲中的数据时出现网络错误,那么recv函数返回SOCKET_ERROR;

(2)如果s的发送缓冲中没有数据或者数据被协议成功发送完毕后,recv先检查套接字s的接收缓冲区,如果s接收缓冲区中没有数据或者协议正在接收数据,那么recv就一直等待,直到协议把数据接收完毕。当协议把数据接收完毕,recv函数就把s的接收缓冲中的数据copy到buf中(注意协议接收到的数据可能大于buf的长度,所以在这种情况下要调用几次recv函数才能把s的接收缓冲中的数据copy完。recv函数仅仅是copy数据,真正的接收数据是协议来完成的);

recv函数返回其实际copy的字节数。如果recv在copy时出错,那么它返回SOCKET_ERROR;如果recv函数在等待协议接收数据时网络中断了,那么它返回0。

注意:在Unix系统下,如果recv函数在等待协议接收数据时网络断开了,那么调用recv的进程会接收到一个SIGPIPE信号,进程对该信号的默认处理是进程终止。

#include <stdio.h>#include <stdlib.h>#include <stdbool.h>#include <unistd.h>#include <pthread.h>#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <linux/types.h>#include "protocol.h"#include "wcam.h"int tcp_init_net(char *ip, int port){     int sock;     struct sockaddr_in addr;          sock = socket(AF_INET,SOCK_STREAM,0);          addr.sin_addr.s_addr = inet_addr(ip);     addr.sin_family = AF_INET;     addr.sin_port = htons(port);  //指向数据机构sockaddr的指针,其中包括目的端口和IP地址        if (-1 == connect(sock,(struct sockaddr *)&addr,sizeof(struct sockaddr)))     {//套接字描述符参数sockfd的socket连至参数addr指定的网络地址         close(sock);         return -1;     }          return sock;     }//该函数是老师自己实现不是linux驱动中的int make_request(__u8 *buf,enum request req, __u8 *dat){//需要的请求    __u32 hdr = req;    __u8 *p = buf;    __u8 len;           memcpy(p,&hdr,FRAME_HDR_SZ);//把请求的前3个数据复制到buf        p += FRAME_HDR_SZ;//p指针指向请求第4个数据        len = REQUEST_LEN(req);//用于判断请求有没有附加的数据//    #define REQUEST_LEN(req)    (((req) >> (8*LEN_POS)) & 0xFF)        if (len>0 && dat)    memcpy(p,dat,len);//如果有附加数据就复制到dat        return len+FRAME_HDR_SZ;    }void * video_thread(void *arg){    int len;    struct wcam_cli *client = (struct wcam_cli *)arg;    __u8 *rsp = client->rsp;    int size;        while(!(client->stop))    {    //1. 发送图像请求        //1.1 构造图像请求        len = make_request(client->req, VID_REQ_FRAME, NULL);                //1.2 发送图像请求        send(client->sock,client->req, len ,0);        //套接字描述符发送的数据    //2. 接收图像    len = FRAME_HDR_SZ;    //buf缓冲区    recv(client->sock,rsp,len,MSG_WAITALL);//第1次搜是搜它的格式     //发送端的套接字描述符调用方式     //注意协议接收到的数据可能大于buf的长度,所以在这种情况下要调用几次recv函数才能     //把s的接收缓冲中的数据copy完。recv函数仅仅是copy数据,真正的接收数据是协议来完成的    rsp += FRAME_HDR_SZ;    len = client->rsp[LEN_POS];    recv(client->sock,rsp,len,MSG_WAITALL);//第2次搜是搜它的长度        memcpy(&size,rsp,len);//长度拷贝到size        rsp += len;    //猜测;size作为长度是之前的数据有多大长度就多大    recv(client->sock,rsp,size,MSG_WAITALL);//第3次搜是搜它的实际数据        //3.提交图像给显示子系统    draw_video_frame(rsp,size,client->arg);        usleep(10000);    }}void net_sys_init(struct wcam_win *c){    pthread_t tid;    struct wcam_cli *client;        client = calloc(1,sizeof(struct wcam_cli));    client->stop = false;    client->arg = c;    client->sock = c->entry_win->sock;//这里取到的sock包含了图形界面输入的ip地址    c->client = client;         //2. 构建工作线程运行函数的参数    pthread_create(&tid,NULL,video_thread,client);    //线程运行函数的起始地址}


0 0
原创粉丝点击