信息
[root@xilinx Downloads]# uname -a
Linux xilinx 2.6.32-71.el6.x86_64 #1 SMP Wed Sep 1 01:33:01 EDT 2010 x86_64 x86_64 x86_64 GNU/Linux
我正在尝试使用Unix套接字创建一个简单的聊天应用程序:
编译代码后,我首先在一个终端上运行 server ,然后说,等待连接。然后我在同一台计算机上的另一个终端上启动客户端,它成功连接。然后客户端发送第一条消息。服务器完全接收它。
但在那之后发生了一些奇怪的事情。我必须输入几次以使其工作并获得整个消息。
这是一个简单的运行输出:
服务器端
[root@xilinx Downloads]# ./server
Waiting for a connection...
Connected.
客户端
[root@xilinx Downloads]#
[root@xilinx Downloads]#
[root@xilinx Downloads]# ./client
Trying to connect...
Connected.
SingleWord // cleint将此消息发送到服务器
服务器端
>received<SingleWord //server receives this- good.
IamServer // Now server sends some message
客户端 ///我必须按几次输入才能收到整条消息
echo> Ia>
echo> mS>
echo> er>
echo> ve>
echo> r
请帮我解决这个问题:
代码如下。
Server.c
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#define SOCK_PATH "echo_socket"
int main(void) {
int s, s2, t, len;
struct sockaddr_un local, remote;
char str[100];
char str2[100];
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);
}
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");
done = 0;
do {
while (1) {
n = recv(s2, str, 100, 0);
printf(">received<%s", str);
if (n <= 0) {
if (n < 0) perror("recv");
printf("error");
done = 1;
}
//m = fgets(str2,100,stdin);
if (!done)
while (fgets(str2, 100, stdin) > 0) {
if (send(s2, str2, strlen(str2), 0) < 0) {
perror("send");
//if (send(s2, str2, m, 0) < 0) {
//perror("send");
done = 1;
}
}
}
} while (!done);
close(s2);
}
return (0);
}
Client.c
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#define SOCK_PATH "echo_socket"
int main(void) {
int s, t, len;
struct sockaddr_un remote;
char str[100];
char str2[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 (1) {
while (printf("> "), fgets(str, 100, stdin), !feof(stdin)) {
if (send(s, str, strlen(str), 0) < 0) {
perror("send");
exit(1);
}
if ((t = recv(s, str2, strlen(str2), 0)) > 0) {
str2[t] = '\0';
printf("echo> %s", str2);
} else {
if (t < 0) perror("recv");
else printf("Server closed connection\n");
exit(1);
}
}
}
close(s);
return 0;
}
答案 0 :(得分:1)
您的代码中有一些问题:
server.c:
在n = recv(s2, str, 100, 0);
之后,在使用它之前你不会使null终止 - 你应该有:
n = recv(s2, str, 100, 0);
str[(n > 0) ? n : 0] = '\0';
while(1)
应为while (! done)
,如果您收到错误,则会出现显示错误的无限循环 - 您应该:
do {
while (! done) {
client.c:
您在strlen
recv
使用t = recv(s, str2, strlen(str2), 0)
- 应该是:
if ((t = recv(s, str2, sizeof(str2), 0)) > 0) {
while (1) { while (printf("> "), fgets(str, 100, stdin), !feof(stdin))
没有达到预期效果,如果在stdin上执行eof,外部循环继续 - 你可以编写(上面提到int done = 0
提供):
while (! done) {
done = 1;
while (printf("> "), fgets(str, 100, stdin) != NULL) {
done = 0;
我不保证没有其他相同类型的小问题,你应该与select
进行IO多路复用,因为现在,客户端和服务器必须依次讨论。
答案 1 :(得分:-2)
您可能需要在客户端启动新线程以从服务器接收消息或使用I / O多路复用。