我在服务器中有一个Unix shell,它应该将输出发送到客户端,然后打印出来。我已经尝试了几种不同的方法来获得完整的输出,但我只得到3-5个字母,即使我在recv中使用了一个while循环,它应该能够接收所有内容。
服务器打印出整个输出,但客户端没有收到整个数据。
服务器代码:
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#define EXIT_SUCCESS 0
#define EXIT_FAILURE 1
#include <errno.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/wait.h>
#define SOCK_PATH "echo_socket"
#define ORDLANGD 30
#define die(e) do { fprintf(stderr, e); exit(EXIT_FAILURE); } while (0);
void byt(char *foo);
void lasIn(char *a1, char *argv[]);
static void pSigHandler(int signo){
switch (signo) {
case SIGTSTP:
printf("TSTP");
fflush(stdout);
break;
}
}
int main(void)
{
int s, s2, t, len, newsockfd;
struct sockaddr_un local, remote;
char str[100];
char *argv[7];
char foo[4096];
int link[2];
if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
perror("socket");
exit(1);
}
local.sun_family = AF_UNIX;
strcpy(local.sun_path, SOCK_PATH);
unlink(local.sun_path);
len = strlen(local.sun_path) + sizeof(local.sun_family);
if (bind(s, (struct sockaddr *)&local, len) == -1) {
perror("bind");
exit(1);
}
if (listen(s, 5) == -1) {
perror("listen");
exit(1);
}
struct sigaction psa;
psa.sa_handler = pSigHandler;
sigaction(SIGTSTP, &psa, NULL);
for(;;) {
int done, n;
printf("Waiting for a connection...\n");
t = sizeof(remote);
if ((s2 = accept(s, (struct sockaddr *)&remote, &t)) == -1) {
perror("accept");
exit(1);
}
printf("Connected.\n");
pid_t pid;
pid = fork();
if (pid < 0)
{
perror("ERROR on fork");
exit(1);
}
if (pid == 0)
{
/* This is the client process */
close(s);
done = 0;
do {
n = recv(s2, str, 100, 0);
if (n <= 0) {
if (n < 0) perror("recv");
done = 1;
}
lasIn(str, argv);
if ((strcmp(argv[0], "exit")) == 0){
exit(0);
}
else if ((strcmp(argv[0], "cd")) == 0){
if ((chdir(argv[1])) != 0){
printf("Gar inte att byta katalog\n");
}
}
pid_t pid;
if (pipe(link)==-1)
die("pipe");
if ((pid = fork()) == -1)
die("fork");
if(pid == 0) {
dup2 (link[1], STDOUT_FILENO);
close(link[0]);
execvp(argv[0], argv);
sleep (1);
exit(0);
} else {
close(link[1]);
read(link[0], foo, sizeof(foo));
printf("\n\n%s\n\n", foo);
wait(NULL);
}
if (!done)
{
if (send(s2, foo, n, 0) < 0) {
perror("send");
done = 1;
}
}
} while (!done);
}
else
{
close(s2);
}
}
return 0;
}
void lasIn(char *a1, char *argv[]){
int i;
argv[0] = strtok(a1, " \n");
for(i = 1; i < 6; i = i++) {
argv[i] = strtok(NULL, " \n");
if (argv[i] == NULL)
break;
}
argv[6] = NULL;
}
客户代码:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <netinet/in.h>
#define SOCK_PATH "echo_socket"
int main(void)
{
int s, t, len;
struct sockaddr_un remote;
char str[100];
if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
perror("socket");
exit(1);
}
printf("Trying to connect...\n");
remote.sun_family = AF_UNIX;
strcpy(remote.sun_path, SOCK_PATH);
len = strlen(remote.sun_path) + sizeof(remote.sun_family);
if (connect(s, (struct sockaddr *)&remote, len) == -1) {
perror("connect");
exit(1);
}
printf("Connected.\n");
while(printf("> "), fgets(str, 100, stdin), !feof(stdin)) {
if (send(s, str, strlen(str), 0) == -1) {
perror("send");
exit(1);
}
while(1)
{
memset(str ,0 , 100); //clear the variable
if(recv(s , str , 100 , 0) < 0)
{
break;
}
else
{
printf("%s" , str);
break;
}
}
}
close(s);
return 0;
}
答案 0 :(得分:1)
鉴于您获得了一些,而不是所有预期的流量,可能一个 潜在的 问题是您的代码部分中的两个break;
声明:< / p>
while(1)
{
memset(str ,0 , 100); //clear the variable
if(recv(s , str , 100 , 0) < 0)
{
break;//here
}
else
{
printf("%s" , str);
break;//and here
}
}
第一次进入时,它会在一个或其他分支中突破while循环, 无论 是否有更多数据。
您可以考虑 另外两件事:
1) 使用备用呼叫结构。类似的东西:
while(recv(s , str , 100 , 0) > 0)
{
...
}
//do some error checking here
2) 在成功send(,,,);
和致电recv(,,,)
之间放置一小段(几分之一秒)延迟。
编辑 使用带套接字的终止字符的示例
numBytesReceived = recv(irdaCommSocket, recvBuf, readBufsize, 0);
while(strstr(recvBuf, "%") == NULL)//uniques terminating character (use anything, including `\n`)
{
if (numBytesReceived < 0) return WSAGetLastError();//windows specific, change error handling for linux
strncpy(bufptr, recvBuf, readBufsize);
*pNumBytes += numBytesReceived;
numBytesReceived = recv(irdaCommSocket, recvBuf, readBufsize, 0);
}