练习 C 网络编程:我正在编写一个简单的 TCP 客户端-服务器应用程序,它应该将消息(在每个客户端的单独线程中)作为字符串从服务器发送到客户端并在客户端(稍后将成为控制台商店应用程序)。我首先发送消息的大小,然后使用套接字 write()
函数发送消息本身。服务器端:
void answer(void *arg) {
struct thData tdL;
tdL= *((struct thData*)arg);
// Welcome message
char *initMsgToClient;
getInitialMessage(&initMsgToClient);
int len_initMsgToClient = strlen(initMsgToClient);
// Returning message to client
if ( write (tdL.cl, &len_initMsgToClient, sizeof(int)) <= 0 ) {
printf("[Thread %d] ",tdL.idThread);
perror ("[Thread] Error at write(): len_initMsgToClient to client.\n");
}
if (write (tdL.cl, initMsgToClient, len_initMsgToClient) <= 0) {
printf("[Thread %d] ",tdL.idThread);
perror ("[Thread]Error at write(): initMsgToClient to client.\n");
}
khác
printf ("[Thread %d] Message was sent with success.\n",tdL.idThread);
}
void getInitialMessage(char **paramMessage) {
char *resultMessage = "Welcome to Console Shopper!";
*paramMessage = resultMessage;
}
在客户端,我首先读取大小和消息本身并打印它,但每次运行 ./client
时,我都会在消息中得到不同的随机尾随字符。客户端:
char welcomeMessageFromServer[512];
int lenWelcomeMsg;
// Reading size of first mesage: lenWelcomeMsg
if (read(sd, &lenWelcomeMsg, sizeof(int)) < 0) {
perror ("[client] Error reading len welcome message from server.\n");
}
// Reading initial message from server: welcomeMessageFromServer
if (read(sd, welcomeMessageFromServer, lenWelcomeMsg) < 0) {
perror ("[client] Error reading welcome message from server.\n");
return errno;
}
printf("%s",welcomeMessageFromServer);
printf("\n");
为简单起见,我省略了添加套接字和线程处理的代码,大部分代码来自教程,因此应该是正确的。我很确定我对正在发送/接收的消息的大小做错了什么。我为 ./client
多次运行的输出:
Welcome to Console Shopper!
Welcome to Console Shopper!�
Welcome to Console Shopper!������i0
Welcome to Console Shopper!������UF+:
有些时候它做对了。我应该更正哪些内容才能始终收到正确的消息?
// Reading initial message from server: welcomeMessageFromServer
if (read(sd, welcomeMessageFromServer, lenWelcomeMsg) < 0) {
perror ("[client] Error reading welcome message from server.\n");
return errno;
}
printf("%s",welcomeMessageFromServer);
这里有两个问题:
%s
格式说明符仅适用于 C 风格的字符串。要使您收到的消息成为 C 风格的字符串,您需要在其末尾放置一个终止零字节。
read
函数不能确保它接收到所有请求的字节。您需要检查返回值,如果您没有收到完整消息,请再次调用它。
尝试这样的函数:
ssize_t readAll (int fd, void *vbuf, size_t count)
{
char *buf = (char *) vbuf;
ssize_t read_so_far = 0;
while (count > 0)
{
ssize_t ret = read(fd, buf, count);
if (ret < 0)
return ret;
if (ret == 0)
return read_so_far;
count -= ret;
read_so_far += ret;
buf += ret;
}
return read_so_far;
}
然后你可以这样做:
// Reading initial message from server: welcomeMessageFromServer
if (readAll(sd, welcomeMessageFromServer, lenWelcomeMsg) != lenWelcomeMsg) {
perror ("[client] Error reading welcome message from server.\n");
return errno;
}
welcoemMessageFromServer[lenWelcomeMsg] = 0;
printf("%s",welcomeMessageFromServer);
Tôi là một lập trình viên xuất sắc, rất giỏi!