简体   繁体   English

C 中的客户端和服务器 send() 和 recv()

[英]Client and Server send() and recv() in C

This is my first time socket programming and have a question about send and recv.这是我第一次进行套接字编程,并且对发送和接收有疑问。 I'm sending a file from server to client which works fine.我正在从服务器向客户端发送一个文件,它工作正常。 But, when I want to continue my program with more send() and recv() calls (the commented code at the end of client and server), the client receives this data and writes it to newfile.txt.但是,当我想通过更多的 send() 和 recv() 调用(客户端和服务器末尾的注释代码)继续我的程序时,客户端会接收此数据并将其写入 newfile.txt。

So, my question is, how do I call send() from the server to only send data from test.txt, and then recv() on the client to only receive and write data from test.txt to newfile.txt?所以,我的问题是,如何从服务器调用 send() 仅从 test.txt 发送数据,然后在客户端调用 recv() 仅从 test.txt 接收数据并将其写入 newfile.txt? After this, I would want to continue with my program with more send() and recv() calls which dont get mixed up with the file transfer code.在此之后,我想继续我的程序,使用更多的 send() 和 recv() 调用,这些调用不会与文件传输代码混淆。

Client:客户:

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

int main(int argc, char *argv[]){
    int port = 8001;
    int client_socket;
    struct sockaddr_in server_addr;
    int connect_status;

    client_socket = socket(AF_INET, SOCK_STREAM, 0);    //SOCK_STREAM for TCP
    if (client_socket < 0)
    {
        printf("Error creating socket\n");
        exit(1);
    }
    printf("Socket created\n");

    //address for socket to connect to
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(port);             //8001 arbitrary port
    server_addr.sin_addr.s_addr = INADDR_ANY;

    //connect to address of socket
    connect_status = connect(client_socket, (struct sockaddr *) &server_addr, sizeof(server_addr));
    if(connect_status == -1)
    {
        printf("Error connecting to server\n");
        exit(1);
    }
    printf("Connected to Server\n");




    FILE* fp = fopen( "newfile.txt", "w");
    char data[512];
    int b;

    while((b=recv(client_socket, data, 512,0))>0){
        fwrite(data, 1, b, fp);
    }
    fclose(fp);


    //recv(client_socket, data, 512,0);
    //printf("client buffer: %s\n", data);

    close(client_socket);
    return 0;

}

Server:服务器:

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

int main(int argc, char *argv[]){
    int port = 8001;
    int server_socket;
    struct sockaddr_in server_addr;
    int client_socket, client_addr;
    int bind_status, listen_status;


    server_socket = socket(AF_INET, SOCK_STREAM, 0);    //SOCK_STREAM for TCP
    if (server_socket < 0)
    {
        printf("Error creating socket\n");
        exit(1);
    }
    printf("Socket created\n");

    //address for socket to connect to
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(port);
    server_addr.sin_addr.s_addr = INADDR_ANY;

    //bind socket to the IP and port
    bind_status = bind(server_socket, (struct sockaddr *) &server_addr, sizeof(server_addr));
    if (bind_status < 0)
    {
        printf("Error binding to socket\n");
        exit(1);
    }
    printf("Socket binded\n");

    //listen for client connections
    listen_status = listen(server_socket, 10);
    if (listen_status == -1)
    {
        printf("Error listening to socket\n");
        exit(1);
    }
    printf("Listening\n");

    //accept client connection
    socklen_t addr_len;
    addr_len = sizeof(client_socket);
    client_socket = accept(server_socket, (struct sockaddr *) &client_addr, &addr_len);




    FILE *fp = fopen("test.txt", "r");
    char data[512];
    int b;

    while((b = fread(data, 1, 512, fp))>0){
        send(client_socket, data, b, 0);
    }
    fclose(fp);


   // strcpy(data,"test message");
    //printf("server buffer: %s\n", data);
    //send(client_socket, data, 512, 0);

    close(server_socket);
    return 0;
}

You need some way to indicate the server that you have finished sending a file, and now you want to send another thing.您需要某种方式来指示服务器您已经完成了文件的发送,现在您要发送另一个东西。

While the socket abstraction seems to show you that the recv and send calls are somehow synchronized, this means that the data you send from the client in one call to send is recv'd in the server with exactly one recv, that is not true, due fundamentally to how the sockets are implemented (the client tcp can decide to split your transfer in several packets, and the unattending of the server can make all those packets to buffer n the receiver before the server receives part of them in one call to recve and others in the text call.虽然套接字抽象似乎向您展示了 recv 和 send 调用以某种方式同步,但这意味着您在一次调用 send 中从客户端发送的数据在服务器中被接收到恰好一个 recv,这是不正确的,基本上是由于 sockets 是如何实现的(客户端 tcp 可以决定将您的传输拆分为几个数据包,并且服务器的无人值守可以使所有这些数据包在服务器在一次调用中接收到它们的一部分之前缓冲 n 接收器以接收和其他人在文字通话中。

The only thing sure is that a byte that has been sent before, is receive before, and no repeated or missing bytes in between.唯一可以确定的是,之前发送过的字节是之前接收过的,并且两者之间没有重复或丢失的字节。 But the number of bytes received at some recve call is dictated only by the amount of buffered data that one side of the connection has.但是在某些 recve 调用中接收到的字节数仅取决于连接一侧具有的缓冲数据量。

This means that, for telling the server that you are finished with your file and some other thing is to be sent, you must do something that allows the server to recognize that the data has ended and more data on a different thing is about to come.这意味着,为了告诉服务器您已完成文件并且要发送其他内容,您必须执行一些操作以使服务器能够识别数据已经结束,并且关于不同事物的更多数据即将到来.

There are several approaches here... you can send an inband sequence (some control sequence) that, wen read in the other side, will be recognized as the end of a block of data and the beginning of the next.这里有几种方法......您可以发送一个带内序列(一些控制序列),在另一边读取时,它将被识别为数据块的结尾和下一个数据块的开头。 Some systems use a packet encoding that simply prepends each block with a number of bytes to follow, and an empty packet (eg a single number 0, meaning 0 bytes to follow) can represent this sequence.一些系统使用分组编码,它简单地在每个块前面加上要跟随的字节数,并且一个空分组(例如,单个数字 0,意味着要跟随 0 个字节)可以表示这个序列。 Another way, can be to use a specific sequence you know is improbable to occur in the data (eg \n.\m , two newlines with one dot interspersed ---this has been used many times in unix's ed editor, for example, or the post office protocol uses it.) and if it is the case that such a sequence happens to be in the file, just double the dot, to indicate that it is not the separator sequence.另一种方法,可以是使用您知道不可能出现在数据中的特定序列(例如\n.\m ,两个换行符,其中一个点穿插——这已在 unix 的 ed 编辑器中多次使用,例如,或邮局协议使用它。)如果是这样的序列恰好在文件中,只需将点加倍,以表明它不是分隔符序列。 And both ends must agree on this (so called) protocol.并且两端必须就这个(所谓的)协议达成一致。

Other mechanisms are valid, you can close the connection and use another socket for a new data exchange.... for example, FTP protocol uses this approach by using one control connection for FTP commands, while using other connections for data transfers.其他机制是有效的,您可以关闭连接并使用另一个套接字进行新的数据交换......例如,FTP 协议使用这种方法,通过对 FTP 命令使用一个控制连接,同时使用其他连接进行数据传输。

I have not included code because there are plenty of examples in the literature.我没有包含代码,因为文献中有很多例子。 Try to get access to the book "Unix Network Programming" of Richard W. Stevens.尝试访问 Richard W. Stevens 的“Unix Network Programming”一书。 That's a very good reference to get initiated on socket protocols and how to deal with all these things.这是开始学习套接字协议以及如何处理所有这些事情的一个很好的参考。

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

相关问题 C、recv_all、send_all 中的 TCP 回显服务器/客户端 - 由我实现,recv 不起作用 - TCP echo server / client in C, recv_all, send_all - implemented by me, recv does not work TCP / IP轮询客户端在c中发送和接收 - TCP/IP polling client send and recv in c 如何在 udp 服务器(在 c 中)和 udp 客户端(python)之间发送和接收 c 结构? - how to send and recv c struct between udp server(in c) and udp client(python)? C文件服务器和客户端挂在recv上 - C file server and client hanging on recv (C套接字编程)将服务器的send()调用与结束于同一客户端recv()缓冲区中的服务器分开 - (C Socket Programming) Seperate send() calls from server ending up in same client recv() buffer Winsock:服务器上的 recv() 被阻塞,但客户端已经移过 send() - Winsock: recv() on Server is blocking, but client has already moved past send() C套接字客户端没有recv() - 来自服务器的任何字节 - C Socket Client not recv()-ing any bytes from server C 客户端:recv 未按预期运行 - C Client : recv not functioning as expected C 套接字:同时接收和发送 - C socket: recv and send simultaneously 有什么方法可以知道从客户端发送到服务器的字节数并在网络中处理 recv() - Is there any way to know the amount of bytes send from the client to the server and process the recv() in networks
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM