实践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");
}
else
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+:
有时候它会正确。为了始终获得正确的消息,我应该纠正什么?
答案 0 :(得分:1)
// 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);