Unix套接字:客户端在第一条消息后停止正确接收消息

时间:2014-10-04 06:52:04

标签: c linux sockets unix

信息

[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;
}

2 个答案:

答案 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多路复用。