交流电插座:recv和send所有数据 [英] C socket: recv and send all data
问题描述
我想获得一个类似的行为:
- 服务器运行
- 客户端运行
- 客户端类型,如帮助或其他 命令
- 服务器作适当的反应
- 去3
问题是,当我的功能excCommand(帮助)运行只是一个小的文本被接收并打印。
我的文本文件是这样的:
命令帮助:帮助 - 显示帮助
退出 - 关闭客户端
只是命令的帮助打印。
另一个问题是,当我键入命令没有打印后2命令的客户端退出。
这是特别的片
而(退出)
{
函数getline(客户机gt;中,命令,10);
如果(STRCMP(指挥,跳槽)== 0)
退出= 0;
其他
excCommand(命令);
}
这是服务器:
的#include<&stdio.h中GT;
#包括LT&;&stdlib.h中GT;
#包括LT&;&string.h中GT;
#包括LT&;&unistd.h中GT;#包括COMMON.HINT主(INT ARGC,CHAR *的argv [])
{
如果(的argc!= 2)
ErrorWithUserMessage(参数(S),<服务器端口>); 字符*服务=的argv [1]; INT servSock = SetupTCPServerSocket(服务);
如果(servSock℃,)
ErrorWithUserMessage(SetupTCPServerSocket()失败,无法确定); unsigned int类型childProcessCount = 0;
而(1)
{
INT clntSock = AcceptTCPConnection(servSock); 将为pid_t进程ID = fork()的;
如果(进程ID℃,)
ErrorWithSystemMessage(叉()失败);
否则,如果(进程ID == 0)
{
关闭(servSock);
HandleTCPClient(clntSock);
出口(EXIT_SUCCESS);
} 输出(与子进程数:%d \\ n,进程ID);
关闭(clntSock);
childProcessCount ++; //清理僵尸
而(childProcessCount)
{
进程ID = waitpid函数((将为pid_t) - 1,NULL,WNOHANG);
如果(进程ID℃,)
ErrorWithSystemMessage(waitpid函数()失败);
否则,如果(进程ID == 0)
打破;
其他
childProcessCount--;
} }}
处理器:
无效HandleTCPClient(INT clntSock)
{
字符缓冲区[BUFSIZE];
ssize_t供numBytesRcvd =的recv(clntSock,缓冲器,BUFSIZE,0);
缓冲[numBytesRcvd] ='\\ 0';
如果(numBytesRcvd℃,)
ErrorWithSystemMessage(的recv()失败);
如果(STRCMP(缓冲,帮助)== 0)
{
FILE *计划生育=的fopen(的help.txt,R);
如果(FP)
{
焦线[128];
而(与fgets(线,的sizeof(线),FP)!= NULL)
{
如果(发送(clntSock,行,的sizeof(线),0)℃下)
ErrorWithSystemMessage(寄()失败);
}
FCLOSE(FP);
}
} 关闭(clntSock);
}
这是我的客户:
的#include<&stdio.h中GT;
#包括LT&;&stdlib.h中GT;
#包括LT&;&string.h中GT;
#包括LT&;&unistd.h中GT;#包括LT&; SYS / types.h中>
#包括LT&; SYS / socket.h中>#包括COMMON.HINT袜子;无效函数getline(字符*消息,字符* buf中,诠释MAXLEN)
{
的printf(%S,消息);
与fgets(BUF,MAXLEN,标准输入);
的buf [strlen的(BUF) - 1] = 0;
}无效excCommand(字符*命令)
{
如果(发送(袜子,命令,strlen的(命令),0)℃下)
ErrorWithSystemMessage(寄()失败); 焦炭replyMessage [BUFSIZE];
ssize_t供numBytesRecv = 0;
做
{
numBytesRecv =的recv(袜子,replyMessage,BUFSIZE,0);
如果(numBytesRecv℃,)
ErrorWithSystemMessage(的recv()失败);
的printf(%S \\ n,replyMessage);
memset的(安培; replyMessage,0,sizeof的(replyMessage)); }
而(numBytesRecv大于0);
}无效PrintFile(为const char *文件名)
{
FILE * FP;
FP = FOPEN(文件名,R);
如果(FP)
{
焦线[128];
而(与fgets(线,的sizeof(线),FP)!= NULL)
的fputs(线,标准输出);
的fputs(\\ n,标准输出);
FCLOSE(FP);
}
}INT主(INT ARGC,CHAR *的argv [])
{
INT退出= 1;
字符命令[10]; 如果(argc个2 ||的argc→3)
{
ErrorWithUserMessage(参数(S),<服务器地址><服务器端口>);
} 字符*服务器=的argv [1];
字符*服务=的argv [2]; 袜子= SetupTCPClientSocket(服务器,服务);
如果(袜子℃,)
ErrorWithUserMessage(SetupTCPClientSocket()失败,无法连接); 的printf(连接建立\\ n \\ n!); PrintFile(menu.txt);
excCommand(帮助); 而(退出)
{
函数getline(客户机gt;中,命令,10);
如果(STRCMP(指挥,跳槽)== 0)
退出= 0;
其他
excCommand(命令);
} 的fputs(\\ n,标准输出);
关闭(袜子);
出口(EXIT_SUCCESS);
}
抱歉这么啰嗦P>
的的recv()
和发送()
函数不保证发送/ recv的所有数据(见人的recv ,的人送上)
您需要实现自己的 send_all()
和 recv_all()
,像
布尔send_all(INT插座,无效*缓冲区,为size_t长度)
{
字符* PTR =(字符*)缓冲;
而(长度大于0)
{
INT I =发送(插座,PTR,长度);
如果(I< 1)返回false;
PTR + =我;
长度 - =我;
}
返回true;
}
下面的指南可以帮助您 Beej的指南网络编程
I would like to obtain a behavior similar to this:
- Server run
- Client run
- Client type a command like "help" or other
- Server responds appropriately
- go to 3
The problem is that when my function excCommand("help") run just a little text is received and printed. My text file is this:
COMMAND HELP:
help - Display help
quit - Shutdown client
only COMMAND HELP is printed. Another problem is that when i type a command nothing is printed and after 2 command client exit. This is the piece in particular:
while (quit)
{
getLine("client> ", command, 10);
if (strcmp(command, "quit") == 0)
quit = 0;
else
excCommand(command);
}
This is the server:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "common.h"
int main(int argc, char *argv[])
{
if (argc != 2)
ErrorWithUserMessage("Parameter(s)", "<Server Port>");
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--;
}
}
}
Handler:
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);
}
and this is my client:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#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)
ErrorWithSystemMessage("recv() failed");
printf("%s\n", replyMessage);
memset(&replyMessage, 0, sizeof(replyMessage));
}
while (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 < 2 || argc > 3)
{
ErrorWithUserMessage("Parameter(s)", "<Server Address> <Server Port>");
}
char *server = argv[1];
char *service = argv[2];
sock = SetupTCPClientSocket(server, service);
if (sock < 0)
ErrorWithUserMessage("SetupTCPClientSocket() failed: ", "unable to connect");
printf("Connection established!\n\n");
PrintFile("menu.txt");
excCommand("help");
while (quit)
{
getLine("client> ", command, 10);
if (strcmp(command, "quit") == 0)
quit = 0;
else
excCommand(command);
}
fputs("\n", stdout);
close(sock);
exit(EXIT_SUCCESS);
}
sorry for being so long-winded
The recv()
and send()
functions do not guarantee to send/recv all data (see man recv, man send)
You need to implement your own send_all()
and recv_all()
, something like
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;
}
The following guide may help you Beej's Guide to Network Programming
这篇关于交流电插座:recv和send所有数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!