我正在尝试创建一个服务器和客户端程序,它从客户端向服务器发送字符串,服务器在该服务器上执行该字符串并将输出发送回客户端。我在linux中这样做,我很困惑为什么我的程序不能正常工作。这是代码。
**Client**
int main()
{
//Code to use unix socket here
if (connect(s, (struct sockaddr *)&remote, len) == -1) {
perror("connect");
exit(1);
}
printf("Connected.\n");
while(printf("> "), fgets(str, MAX, stdin), !feof(stdin)) {
if (send(s, str, strlen(str), 0) == -1) {
perror("send");
exit(1);
}
}
done=0;
do {
if(t=recv(s, str, MAX, 0)<0)
perror("recv failed at client side!\n");
str[t] = '\0';
if(strcmp(str, "ENDOFTRANS")==0)
{
printf("\nRead ENDOFTRANS. Breaking loop.\n");
done=1;
}
printf("Server > %s", str);
} while(!done);
}
然后服务器代码是:
**Server**
#define MAX 1000
int main(void)
{
//Unix socket code
//This process is now a daemon.
daemon();
//Listens for client connections, up to 5 clients can queue up at the same time.
if (listen(s, 5) == -1) {
perror("listen");
exit(1);
}
for(;;) {
int done, n, status;
printf("Waiting for a connection...\n");
t = sizeof(remote);
if ((newsock= accept(s, (struct sockaddr *)&remote, &t)) == -1) {
perror("accept");
exit(1);
}
printf("Connected.\n");
done = 0;
do {
switch(fork())
{
case -1: //ERROR
perror("Could not fork.\n");
break;
case 0: //CHILD
//Accept string from client.
//Edit: Why am I getting an error here? says: Invalid argument.
if(n = recv(newsock, str, MAX, 0)) {
perror("Recv error at server side.\n");
exit(1);
}
str[n]='\0';
if (n <= 0) {
if (n < 0)
perror("recv");
done = 1;
}
printf("String=>%s<",str);
//Redirect socket to STDOUT & STDERR.
test = close(WRITE); assert(test==0);
test = dup(newsock); assert(test==WRITE);
test = close(ERROR); assert(test==0);
test = dup(newsock); assert(test==ERROR);
if (!done)
{
if (str==something)
{
//execute command
}
else {
//Fork and execvp the command
}
//Sends End of Transaction character.
ENDTHETRANS();
exit(0);
}
break;
default: //PARENT
//Parent keeps accepting further clients.
wait(&status);
if ((newsock= accept(s, (struct sockaddr *)&remote, &t)) == -1) {
perror("accept");
exit(1);
}
printf("Connected.\n");
done=1;
break;
}
} while (!done);
}
close(s);
}
我对编程一般都比较新,根据我的理解,客户端代码很好,只是当它从服务器收回文本时它只收到小位文本(一次2行)。我必须继续按下客户端promt上的输入以获得剩余的输入。我已经尝试了很多东西,到目前为止我甚至都不知道自己做错了什么。
首先,在服务器代码中,在从客户端收到字符串后,我有一个输出字符串的printf("String=>%s<",str);
。但是,当服务器将输出打印为String=>ls -l
时,最后的<
键会以某种方式被吃掉。它不应该这样做吗?
任何帮助非常感谢。请记住,我是一名初学者,之前只使用过管道作为进程间通信。现在我想制作我的第一个unix socket程序。
提前致谢。
答案 0 :(得分:2)
在这种情况下的常见问题是没有意识到SOCK_STREAM套接字不保留消息边界。因此,通过send
调用发送的数据可能会被分割并在多个recv
中收到,或者可能会合并,而多个send
最终会在一个recv
中结束。最重要的是,当内核发送缓冲区填满时,send
调用可能会写入部分数据(仅发送一些请求的数据)并返回一个短的返回值。您需要对此进行测试并重新发送其余数据。
经常出现的另一个问题是行结尾的问题(特别是在linux和windows之间进行交谈时)。客户端或服务器中可能存在额外的回车字符(\r
),这会混淆另一方。这些在打印时往往会导致输出明显丢失或截断。
修改强>
该行
if(t=recv(s, str, MAX, 0)<0)
相当于
if(t = (recv(s, str, MAX, 0)<0))
即,根据是否存在错误,将t设置为0或1。与此类型的大多数错误一样,打开警告会给你一些指示。