Sockets 选择套接字调用发送和接收同步

Sockets 选择套接字调用发送和接收同步,sockets,network-programming,Sockets,Network Programming,我正在使用select呼叫并接受来自“X”个客户端的连接。 我进行了双工连接,即服务器到客户端和客户端到服务器。 当两个实体之间建立连接时,我将发送 从一个实体到另一个实体的数据块。 在发送过程中,我以块的形式读取一个文件,并以块的形式发送数据 while(file_size !=0) { read_bytes = read(fd, buff, sizeof(buff)); cnt_ = send(_sock_fd,buff,actually_read,0); file_

我正在使用select呼叫并接受来自“X”个客户端的连接。 我进行了双工连接,即服务器到客户端和客户端到服务器。 当两个实体之间建立连接时,我将发送 从一个实体到另一个实体的数据块。 在发送过程中,我以块的形式读取一个文件,并以块的形式发送数据

while(file_size !=0)
{
    read_bytes = read(fd, buff, sizeof(buff));
    cnt_ = send(_sock_fd,buff,actually_read,0);
    file_size = file_size - cnt_;
    printf("total sent remaining %d : %d\n",size,actually_read);
}
在接收端时 //首先,我发送包含大小的头,它被很好地接受,但在接下来的发送调用中,我使用了“get_readable_bytes”(使用ioctl),它返回到达套接字的字节数 `while(大小!=0) { int检验=0

    while(((cnt_= get_readable_bytes(_sock_fd))== 0) )//&& test_ == 0
    {
        cnt_= get_n_readable_bytes(_sock_fd);
        printf("Total bytes recved %d\n",cnt_);
        //test_ = test_ + 1;
    }

    while(cnt_ != 0)
    {
        actually_read = recv(_sock_fd, buff, sizeof(buff),0);
        int _cnt = get_n_readable_bytes(_sock_fd);
        printf("Total bytes recved %d\n",cnt_-_cnt);
        write(_fd,buff,actually_read);
        cnt_ = cnt_ - actually_read;
        test_ = 0;
    }
`现在的问题是 1.在执行接收功能的过程中,控制自动转到选择功能,并尝试再次执行整个接收功能,因此是否有任何方法同步发送方和接收方,以便在发送方完成后启动接收方或发送方启动接收方? 2.如何维护发送和接收的字节数。 这是我的选择电话

`is_read_availble = select(maxfd + 1,&read_set,NULL,NULL,&timeout)`

超时10秒。

概述您需要的缓冲区代码类型。(为了允许部分读/写,缓冲区需要在调用之间保持不变)顺便说一句:您确实需要处理read()和write()的-1返回,因为它们会严重干扰您的缓冲区簿记。EINTR+EAGAIN/EWOULDBLOCK非常常见

struct buff {
        unsigned size;
        unsigned bot;
        unsigned top;
        char *buff;
        };
struct buff bf = {0,0,0,NULL};

initialisation:

bf.buff = malloc(SOME_SIZE);
        /* ... error checking omitted */
bp.size = SOME_SIZE;
bp.bot = bp.top =0;

reading:

unsigned todo;
int rc;

        /* (maybe) shift the buffer down to make place */
todo =  bf.top - bf.bot;
if (todo) {
        memmove (bf.buff, bf.buff + bf.bot, todo);
        bf.top = todo; bf.bot = 0;
        }

todo = bf.size - bf.top;

if (!todo) { /* maybe throttle? ... */ return; }
rc = read (fd, bf.buff+bp.top, todo);
        /* ... error checking omitted */
if (rc == -1) switch (errno) {...}
else if (rc == 0) {...}
else    {
        total_read += rc;
        bp.top +=  rc;
        }


writing:

unsigned todo; 
int rc;

todo =  bf.top - bf.bot;
if (!todo) { /* maybe juggle fd_set ... */ return; }
rc = write (fd, bf.buff+bp.bot, todo);
        /* ... error checking omitted */
if (rc == -1) switch (errno) {...}
else if (rc ==0) { ...}
else    {
        bp.bot += rc;
        total_written += rc;
        if (bp.bot == bp.top) bp.bot = bp.top =0;
        }
/* ... this is the place to juggle the fd_set for writing */

好的:不要将函数的写入部分放在select部分的读取处理程序中,而不是。要么在select循环中为写入设置一个额外的fd_集,要么每次都检查读取缓冲区中是否还有要写入的内容。调用select()当你仍然有工作要做时,是什么阻碍了你。在大多数情况下,每个(对)文件描述符都有某种缓冲区结构是很方便的。我认为这一个可能会对你有所帮助: