繁体   English   中英

使用C中的套接字在多个客户端上传输文件时出现格式错误

[英]Formatting errors while transferring files over multiple clients using Sockets in C

我正在尝试实现一个简单的代码测试器:ACM ICPC或Google Code Jam在线判断器的非常基本的版本。

评估部分有效(到目前为止),但是我对文件传输部分很傻。

基本上我的设置是这样的:

我有一台服务器(始终打开),并且有多个客户端系统属于团队,这些团队将提交其代码。 他们可以在团队中相互传输文件,但是服务器将保留传输日志。 服务器有时可能会向所有或某些客户端发送公告。 最终代码将提交给特定的空客户端计算机进行评估。

现在,我的服务器端代码遇到了麻烦。 我正在使用

select(fdmax+1, &read_fds, NULL, NULL, NULL)

识别准备好向我写入数据的客户端-我知道可以通过fork()以某种方式进行此轮询,但是我对此既不确定也不满意。

为了将数据接收到服务器,我使用以下功能:

void send_recv(int i, fd_set *master, int sockfd, int fdmax)
{
    int nbytes_recvd, j;
    char recv_buf[BUFSIZE], buf[BUFSIZE];

    if ((nbytes_recvd = recv(i, recv_buf, BUFSIZE, 0)) <= 0) {
        if (nbytes_recvd == 0) {
            printf("socket %d hung up\n", i);
        }else {
            perror("recv");
        }
        close(i);
        FD_CLR(i, master);
    }else {
        FILE *logger;
        logger = fopen(fname2, "w");
        fprintf(logger,"Client %i> %s", i,recv_buf);
        for(j = 0; j <= fdmax; j++){
            send_to_all(j, i, sockfd, nbytes_recvd, recv_buf, master );
        }
    }
}

在这里,我得到的是混乱的混乱局面,而不是单独记录通过流传输的所有文件数据,它很难解析。

此功能实际上是在传输文件(全部为ANSI * .c):

void send_to_all(int j, int i, int sockfd, int nbytes_recvd, char *recv_buf, fd_set *master)
{
    if (FD_ISSET(j, master)){
        if (j != sockfd && j != i) {    //prevents data rewrite to incoming host
            int client;
            sscanf(recv_buf, "%d >", &client);
            if(client == 0){                //universal send
                if (send(j, recv_buf, nbytes_recvd, 0) == -1) {
                    perror("send");
                }
            }                               //send to specified host
            else if (send(client, recv_buf, nbytes_recvd, 0) == -1) {
                perror("send");
            }
        }
    }
}

在这里,传入的文件会丢失所有格式,并且每次都会打印两次。

我的服务器代码的精简版在这里: http : //codepad.org/TTejTfbL

我的问题是,我在根本上做错了吗? 我的逻辑(进而扩展为我的代码)是否无法恢复?

如果有人能指出我正确的方向,我将感到满意。 甚至告诉我把它全部扔掉,然后从头开始。 (^; __; ^)

您不能假设您可以在单个调用中send()任何数量的数据,并使其整体成功或失败。 库实现的缓冲区有限制。

您完全有可能传递例如20 KB的send() ,并在仅发送4,711字节后使其成功返回。 这将需要您以适当的数量在缓冲区中前进,减少“要传输的字节”,然后重试。

在您发送完所有数据或从套接字接收到I / O错误之前,这需要循环进行。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM