C socket:recv并发送所有数据
我想获得类似于此的行为:
- 服务器运行
- 客户端运行
- 客户端键入“帮助”或其他命令
- 服务器响应得当
- 去3
问题是,当我的函数excCommand(“help”)运行时,只接收并打印一个小文本。 我的文本文件是这样的:
COMMAND HELP: help - Display help quit - Shutdown client
仅打印命令帮助。 另一个问题是,当我键入命令时,没有打印任何内容,并且在2命令客户端退出之后。 特别是这件作品:
while (quit) { getLine("client> ", command, 10); if (strcmp(command, "quit") == 0) quit = 0; else excCommand(command); }
这是服务器:
#include #include #include #include #include "common.h" int main(int argc, char *argv[]) { if (argc != 2) ErrorWithUserMessage("Parameter(s)", ""); char *service = argv[1]; int servSock = SetupTCPServerSocket(service); if (servSock < 0) ErrorWithUserMessage("SetupTCPServerSocket() failed: ", "unable to establish"); unsigned int childProcessCount = 0; while (1) { int clntSock = AcceptTCPConnection(servSock); pid_t processID = fork(); if (processID < 0) ErrorWithSystemMessage("fork() failed"); else if (processID == 0) { close(servSock); HandleTCPClient(clntSock); exit(EXIT_SUCCESS); } printf("with child process: %d\n", processID); close(clntSock); childProcessCount++; //clean up zombies while (childProcessCount) { processID = waitpid((pid_t) - 1, NULL, WNOHANG); if (processID < 0) ErrorWithSystemMessage("waitpid() failed"); else if (processID == 0) break; else childProcessCount--; } } }
处理器:
void HandleTCPClient(int clntSock) { char buffer[BUFSIZE]; ssize_t numBytesRcvd = recv(clntSock, buffer, BUFSIZE, 0); buffer[numBytesRcvd] = '\0'; if (numBytesRcvd < 0) ErrorWithSystemMessage("recv() failed"); if (strcmp(buffer, "help") == 0) { FILE *fp = fopen("help.txt", "r"); if (fp) { char line[128]; while (fgets(line, sizeof(line), fp) != NULL) { if (send(clntSock, line, sizeof(line), 0) < 0) ErrorWithSystemMessage("send() failed"); } fclose(fp); } } close(clntSock); }
这是我的客户:
#include #include #include #include #include #include #include "common.h" int sock; void getLine(char *message, char *buf, int maxLen) { printf("%s", message); fgets(buf, maxLen, stdin); buf[strlen(buf) - 1] = 0; } void excCommand(char *command) { if ( send(sock, command, strlen(command), 0) < 0) ErrorWithSystemMessage("send() failed"); char replyMessage[BUFSIZE]; ssize_t numBytesRecv = 0; do { numBytesRecv = recv(sock, replyMessage, BUFSIZE, 0); if ( numBytesRecv 0); } void PrintFile(const char *filename) { FILE *fp; fp = fopen(filename, "r"); if (fp) { char line[128]; while (fgets(line, sizeof(line), fp) != NULL) fputs(line, stdout); fputs("\n", stdout); fclose(fp); } } int main(int argc, char *argv[]) { int quit = 1; char command[10]; if (argc 3) { ErrorWithUserMessage("Parameter(s)", " "); } char *server = argv[1]; char *service = argv[2]; sock = SetupTCPClientSocket(server, service); if (sock ", command, 10); if (strcmp(command, "quit") == 0) quit = 0; else excCommand(command); } fputs("\n", stdout); close(sock); exit(EXIT_SUCCESS); }
抱歉这么啰嗦
recv()
和send()
函数不保证发送/ recv所有数据(参见man recv , man send )
你需要实现自己的send_all()
和recv_all()
,比如
bool send_all(int socket, void *buffer, size_t length) { char *ptr = (char*) buffer; while (length > 0) { int i = send(socket, ptr, length); if (i < 1) return false; ptr += i; length -= i; } return true; }
以下指南可以帮助您Beej的网络编程指南
通常的问题。
void excCommand(char *command) { if ( send(sock, command, strlen(command), 0) < 0) ErrorWithSystemMessage("send() failed"); char replyMessage[BUFSIZE]; ssize_t numBytesRecv = 0; do { numBytesRecv = recv(sock, replyMessage, BUFSIZE, 0); if ( numBytesRecv < 0) ErrorWithSystemMessage("recv() failed"); printf("%s\n", replyMessage);
无效。 numBytesRecv
可能为零,在这种情况下根本没有消息,否则此时它必须是正数,因为您已经测试为负数,并且它指示消息的实际长度,这不一定是空的 -终止。 改成:
if (numBytesRecv == 0) break; printf("%.*s\n", numBytesRecv, replyMessage);
然后:
memset(&replyMessage, 0, sizeof(replyMessage));
无意义。 去掉。
} while (numBytesRecv > 0);
此时你应该检查numBytesRecv < 0
并调用perror()
或其中一个朋友。
如果我必须继续或不继续,我选择在每次发送()之前发送。
所以我首先有3个定义
#define BUFFSIZE 1024 #define CONT "CONT" #define DONE "DONE"
然后发送我的数据
int send_to_socket(int sock, char *msg) { size_t len; int ret[2]; len = strlen(msg); ret[0] = send(sock, (len <= BUFFSIZE) ? DONE : CONT, 4, 0); ret[1] = send(sock, msg, BUFFSIZE, 0); if (ret[0] <= 0 || ret[1] <= 0) { perror("send_to_socket"); return (-1); } if (len > BUFFSIZE) return (send_to_socket(sock, msg + BUFFSIZE)); return (1); }
接收它:
char *recv_from_socket(int cs) { char state[5]; char buff[BUFFSIZE+1]; char *msg; int ret[2]; msg = NULL; while (42) { bzero(state, 5); bzero(buff, BUFFSIZE+1); ret[0] = recv(cs, state, 4, 0); ret[1] = recv(cs, buff, BUFFSIZE, 0); if (ret[0] <= 0 || ret[1] <= 0) { perror("recv_from_socket"); return (NULL); } // strfljoin() is selfmade // join the string and free the left argument to prevent memory leaks. // return fresh new string msg = (msg) ? ft_strfljoin(msg, buff) : strdup(buff); if (strncmp(state, DONE, 4) == 0) break ; i++; } return (msg); }