使用socket传输图像

传输图像与传输其他什么数据在我看来并没有什么本质区别,主要是做好帧同步就行了(标定图片的开始行):

接收:

//头文件
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<arpa/inet.h>


int sockfd=socket(AF_INET,SOCK_DGRAM,0);//
 //创建本机对象
struct sockaddr_in addr;
addr.sin_family =AF_INET;
addr.sin_port =htons(8888);//默认的端口号貌似要大于1024,这里随便给的是8888
addr.sin_addr.s_addr=inet_addr("192.168.1.0");//local ip
int ret =bind(sockfd,(struct sockaddr*)&addr,sizeof(addr));//绑定本机端口
if(0>ret)
    {
        printf("bind\n");
        return -1;

    }
//创建对象机
struct sockaddr_in cli;//定义对象机的套接字
cli.sin_addr.s_addr=inet_addr("192.168.100.105");//对象机ip
socklen_t len=sizeof(cli);


unsigned char *data=new unsigned char[1824*940*3];//数据接收数据,传输的图像是1824*940的3//通道图像,分940个包,一次传一行,帧开始时会发送一个300的整数

//设置缓冲区
int optval=1824*940*10;
int optLEn=sizeof(int);
setsockopt(sockfd,SOL_SOCKET,SO_RCVBUF,(char*)&optval,optLEn);
    while(1)
    {

          int buf;
         recvfrom(sockfd,&buf,sizeof(buf),0,(struct sockaddr*)&cli,&len);
         if(buf==300)
         {
              for(int i=0;i<940;i=i+1)
              {

                    int rec=recvfrom(sockfd,data+i*1824*3,sizeof(unsigned char)*1824*3,0,(struct sockaddr*)&cli,&len);
               }            
              cv::Mat im=cvCreateMat(940,1824,CV_8UC3);
              memcpy(im.data,data,sizeof(unsigned char)*1824*940*3);
              imshow("im",im);
              cv::waitKey(1);
  
               im.setTo(0);
               memset(data,0,sizeof(unsigned char)*1824*940*3);
               buf=0;
               im.release();

         }
                 
    }
    close(sockfd);

发送:

    sockfd=socket(AF_INET,SOCK_DGRAM,0);
    addr.sin_family =AF_INET;
    addr.sin_port =htons(8888);
    addr.sin_addr.s_addr=inet_addr("192.168.1.0");//对象ip
    len=sizeof(addr);
    //设置缓冲区
    int optval=1824*940*10;
    setsockopt(sockfd,SOL_SOCKET,SO_RCVBUF,(char*)&optval,sizeof(int));

    unsigned char *data=new unsigned char[gheight*gwidth*3];

    while(1) {       
        memcpy(data,frame.data,sizeof(unsigned char)*gwidth*gheight*3);
        int rec;
        double start=getTickCount();
        int flag=300;
        sendto(sockfd,&flag,sizeof(flag),0,(struct sockaddr*)&addr,len);//发送帧头
        for(int i=0;i<gheight;i++)
        {
         rec=sendto(sockfd,data+i*gwidth*3,sizeof(unsigned char)*gwidth*3,0,(struct sockaddr*)&addr,len);//一行一行的发送图像
          
        }
             }

结果:

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

socket函数类似于open,用来打开一个网络连接,如果成功则返回一个网络文件描述符(int类型),之后我们操作这个网络连接都通过这个网络文件描述符。

dimain:域,网络域,网络地址范围(IPV4或IPV6等),也就是协议簇

type:指定套接字类型:SOCK_STREAM(TCP网络)、SOCK_DGRAM(UDP)、SOCK_SEQPACKET

protocol:指定协议,如果指定0,表示使用默认的协议

                            IPPROTO_IP       IP传输协议

                            IPPROTO_TCP      TCP传输协议

                            IPPROTO_UDP       UDP协议

                            IPPROTO_SCTP      SCTP传输协议

                            IPPROTO_ICMP          ICMP协议

                            IPPROTO_IGMP      IGMP协议

int PASCAL FAR sendto( SOCKET s, const char FAR* buf, int len, int flags,
const struct sockaddr FAR* to, int tolen);

s:一个标识套接口的描述字。
buf:包含待发送数据的缓冲区。
len:buf缓冲区中数据的长度。
flags:调用方式标志位。
to:(可选)指针,指向目的套接口的地址。
tolen:to所指地址的长度。

int PASCAL FAR recvfrom( SOCKET s, char FAR* buf, int len, int flags,
struct sockaddr FAR* from, int FAR* fromlen);

s:标识一个已连接套接口的描述字。
buf:接收数据缓冲区。
len:缓冲区长度。
flags:调用操作方式。
from:(可选)指针,指向装有源地址的缓冲区。
fromlen:(可选)指针,指向from缓冲区长度值。

(至于阻塞不阻塞的问题,我也没有了解那么多,至少这个已经可以用了)

猜你喜欢

转载自blog.csdn.net/weixin_38907330/article/details/81510746
今日推荐