C++ 关于数据包和缓冲区大小的TCP套接字编程

C++ 关于数据包和缓冲区大小的TCP套接字编程,c++,sockets,tcp,C++,Sockets,Tcp,我知道TCP中没有数据包的概念,因为它是一个流套接字,然后举例来说,如果我有一个2000字节的数据包,比如说2000“a”,我的默认缓冲区大小是1024,那么它应该发送两次,接收两次 对于send()函数 iResult = send(s, sendbuf, packet_size, 0); 对于第二个参数,我应该放什么?一个1024字节的发送缓冲区字符指针或一个2000字节的数据包字符指针,它会自动为我处理吗 对于recv()阻塞函数,我应该将缓冲区字符指针放在第二个参数或数据包参数上 对于

我知道TCP中没有数据包的概念,因为它是一个流套接字,然后举例来说,如果我有一个2000字节的数据包,比如说2000“a”,我的默认缓冲区大小是1024,那么它应该发送两次,接收两次

对于send()函数

iResult = send(s, sendbuf, packet_size, 0);
对于第二个参数,我应该放什么?一个1024字节的发送缓冲区字符指针或一个2000字节的数据包字符指针,它会自动为我处理吗

对于recv()阻塞函数,我应该将缓冲区字符指针放在第二个参数或数据包参数上

对于报头,我的朋友建议我添加4字节的报头来存储数据包信息,例如数据包的序列号和大小,如何实现?谢谢


@乔治,谢谢!我还想问,如果我不做部分写入处理,while循环中的发送速率会非常快(没有睡眠),那么服务器端会出现错误/丢失吗?对于recv()


您需要像sendall一样发送,并且(可能)需要编写类似的
receival
。以下是
sendall
(稍加修改):

#包括
#包括
int sendall(int s,char*buf,int*len)
{
int total=0;//我们发送了多少字节
int bytesleet=*len;//我们还有多少要发送
int n=-1;
而(总计<*len){
n=发送(s,buf+总计,字节左,0);
如果(n)
如果我有一个2000字节的数据包,比如说2000‘a’

你没有。你有一个2000字节的消息

我的默认缓冲区大小是1024

不太可能。至少是8192,可能是几千

那么它应该发送两次

至少

收到两次

至少

对于第二个参数,我应该放什么

要发送的消息的大小:在本例中为2000

正在发送缓冲区字符指针,其位置为1024字节

没有

还是一个2000字节的数据包字符指针,它会自动为我处理

对于recv()阻塞函数,我应该将缓冲区字符指针放在第二个参数或数据包参数上

我无法理解这一点,但您应该将接收信息尽可能地放入一个缓冲区并循环,直到您获得整个消息

对于报头,我的朋友建议我添加4字节的报头来存储数据包信息,例如数据包的序列号和大小,如何实现


你不需要序列号,但是消息大小是个好主意。只要把它放在消息的前面。不清楚这里的问题是什么。

为什么不直接返回发送计数,或者-1?为什么是指针参数?@EJP:我展示了该指南中的OP实现,它说发送可能不会发送它被告知的所有数据,类似的是w我猜是阅读。@BenVoight是吗?我本以为是-1。@Giorgi那没有回答我的问题。@EJP:没听懂吗?对,除了“它会自动为我处理”。您需要检查
write
send
调用的返回值,并处理部分写入。@BenVoigt该语句仅适用于
send()
,并且根据Posix在阻塞模式下是正确的,除非存在中断。buf[out]指向缓冲区以接收传入数据的指针。len[in]buf参数指向的缓冲区的长度(字节)。根据MSDN,对于send()情况,我为len[in]输入2000字节,表示我要发送2000字节的缓冲区字符指针。对于recv()情况,我为len[in]输入任意数字参数?如果长度小于2000,它将为我拆分消息,然后等待下一个recv()?@Giorgi,谢谢!我还想问,如果我不进行部分写入处理,并且while循环中的发送速率非常快(无睡眠),那么recv()的服务器端是否会出现错误/丢失@WesPoon这取决于其他因素,例如您是否设置了套接字阻塞或非阻塞,以及是否接收到任何信号。@Giorgi,谢谢!我还想问,如果我不进行部分写入处理,while循环中的发送速率会非常快(无睡眠),那么服务器端是否会出现错误/丢失?对于recv()
SOCKET newsfd;
bind(s, (struct sockaddr *)ReceiverSocket, sizeof(struct sockaddr_in));
if (strcmp(protocol, "tcp") == 0 || strcmp(protocol, "TCP") == 0){
    listen(s, 1);
    newsfd = accept(s, 0, 0);
}

//*** Create Update Display Thread
std::thread th(Function_packet_transmission_display, update_interval, (char*) "recv");

//*** Receive Data//*** Set Jitter
long time_old = 0, time_new = 0, time_start = 0;
long float jitter_new = 0, jitter_old = 0;
long long temp_accubyte = 0, temp_pktnum = 0; //testing
char *recvbuf = new char[buffer_size];
long long next_seq_num = 1; int retVal;
do{

    if (strcmp(protocol, "tcp") == 0 || strcmp(protocol, "TCP") == 0){
        retVal = recv(newsfd, recvbuf, packet_size, 0);
        if ((retVal == SOCKET_ERROR) || (retVal == 0)){
            printf("\nreturn fail code:%i\n", WSAGetLastError());
            closesocket(s);
            WSACleanup();
            lck.lock();
            Ended = true;
            lck.unlock();
            return 0;
        }
    }
    else if (strcmp(protocol, "udp") == 0 || strcmp(protocol, "UDP") == 0){
        int fromlen = (int)sizeof(struct sockaddr_in);
        retVal = recvfrom(s, recvbuf, packet_size, 0, (struct sockaddr *)ReceiverSocket, &fromlen);
    }
    //testing
    temp_accubyte += retVal;
    temp_pktnum++;//TEST
    //printf("\racc: %lld %lld    -   ", temp_accubyte, temp_pktnum);
    //if (temp_pktnum==100000)            printf("\nReach 100000\n", temp_accubyte, temp_pktnum);

    if (timer == NULL){
        timer = new ES_FlashTimer();
    }
#include <sys/types.h>
#include <sys/socket.h>

int sendall(int s, char *buf, int *len)
{
    int total = 0;        // how many bytes we've sent
    int bytesleft = *len; // how many we have left to send
    int n = -1;

    while(total < *len) {
        n = send(s, buf+total, bytesleft, 0);
        if (n <= 0) {  break; }
        total += n;
        bytesleft -= n;
    }

    *len = total;  

    return (n<=0)?-1:0; // return -1 on failure, 0 on success
}