我对TCP / IP套接字编程非常陌生。 client.c有2个argv值 我需要将这两个发送到server.c
我想如果我从client.c发送两次并且在server.c发送两次recv,那会很好,但实际上不是。谁能让我知道如何将两个缓冲区发送到server.c?
在client.c
ssize_t byteNumSentAccName = send(clientSock, accountName, strlen(accountName), 0);
ssize_t byteNumSentCmd = send(clientSock, command, strlen(accountName), 0);
accountName和command都是char缓冲区。
在server.c
ssize_t byteNumRecvAccName = recv(clientSock, nameBuf, BUFSIZE-1, 0);
ssize_t byteNumRecvCmd = recv(clientSock, cmdBuf, BUFSIZE-1, 0);
答案 0 :(得分:1)
TCP是字节流,send()
和recv()
之间没有1:1的关系,就像UDP中一样。
在TCP中,send()
发送的字节少于请求的字节,而recv()
返回的字节少于请求的字节。因此,您需要循环调用它们,直到发送/接收所有字节为止。而且,您需要以一种这样的方式来构造数据,即接收器知道一个值在哪里结束而下一个值在哪里开始。例如,发送可变长度的字符串时,您可以
bool sendRaw(int sock, const void *data, int size)
{
const char *buffer = (const char*) data;
while (size > 0)
{
ssize_t sent = send(sock, buffer, size, 0);
if (sent < 0)
return false;
buffer += sent;
size -= sent;
}
return true;
}
bool sendInt32(int sock, int32_t value)
{
value = htonl(value);
return sendRaw(sock, &value, sizeof(value));
}
bool sendString(int sock, const char *s)
{
int32_t len = strlen(s);
if (!sendInt32(sock, len))
return false;
return sendRaw(sock, s, len);
}
...
sendString(clientSock, accountName);
sendString(clientSock, command);
int readRaw(int sock, void *data, int size)
{
char *buffer = (char*) data;
while (size > 0)
{
ssize_t recvd = recv(sock, buffer, size, 0);
if (recvd < 0)
return -1;
if (recvd == 0)
return 0;
buffer += recvd;
size -= recvd;
}
return 1;
}
int readInt32(int sock, int32_t *value)
{
int ret = readRaw(sock, value, sizeof(*value));
if (ret == 1)
*value = ntohl(*value);
return ret;
}
char* readString(int sock)
{
int32_t len = 0;
if (readInt32(sock, &len) <= 0)
return NULL;
char *ret = (char*) malloc(len+1);
if (!ret)
return NULL;
if (readRaw(sock, ret, len) <= 0)
{
free(ret);
return NULL;
}
ret[len] = '\0';
return ret;
}
...
nameBuf = readString(clientSock);
cmdBuf = readString(clientSock);
...
free(nameBuf);
free(cmdBuf);
bool sendRaw(int sock, const void *data, int size)
{
const char *buffer = (const char*) data;
while (size > 0)
{
ssize_t sent = send(sock, buffer, size, 0);
if (sent < 0)
return false;
buffer += sent;
size -= sent;
}
return true;
}
bool sendString(int sock, const char *s)
{
int32_t len = strlen(s) + 1;
return sendRaw(s, len);
}
sendString(clientSock, accountName);
sendString(clientSock, command);
int readRaw(int sock, void *data, int size)
{
char *buffer = (char*) data;
while (size > 0)
{
ssize_t recvd = recv(sock, buffer, size, 0);
if (recvd < 0)
return -1;
if (recvd == 0)
return 0;
buffer += recvd;
size -= recvd;
}
return 1;
}
char* readString(int sock)
{
char *ret = NULL, *tmp;
size_t len = 0, cap = 0;
char ch;
do
{
if (readRaw(sock, &ch, 1) <= 0)
{
free(ret);
return NULL;
}
if (ch == '\0')
break;
if (len == cap)
{
cap += 100;
tmp = (char*) realloc(ret, cap);
if (!tmp)
{
free(ret);
return NULL;
}
ret = tmp;
}
ret[len] = ch;
++len;
}
while (true);
if (len == cap)
{
tmp = (char*) realloc(ret, cap+1);
if (!tmp)
{
free(ret);
return NULL;
}
ret = tmp;
}
ret[len] = '\0';
return ret;
}
...
nameBuf = readString(clientSock);
cmdBuf = sendString(clientSock);
...
free(nameBuf);
free(cmdBuf);