嵌入式设备上的Unix域套接字代码失败

时间:2013-12-02 16:16:30

标签: c sockets unix unix-socket

我已经在我正在处理的项目中添加了一个Unix域套接字。套接字有一个简单的功能,它只是广播代码从另一个设备中提取的数据,其想法是其他应用程序将能够从套接字读取这些数据。

我编写了一个简单的服务器代码,当我在笔记本电脑上运行代码时,使用Ubuntu 10.04 VM,它运行得非常好。但是,当我将代码复制到嵌入式设备上时,我正在使用代码失败,当我的应用程序尝试写入套接字时代码退出。

/var/log/messages中,我看到以下消息:

Dec  2 15:12:17 box local1.info my-app[17338]: Socket Opened
Dec  2 15:12:17 box local1.err my-app[17338]: Socket Failed
Dec  2 15:12:17 box local1.err my-app[17338]: Protocol wrong type for socket
Dec  2 15:12:38 box local1.info ./server[17178]: accept failed: Invalid argument

这是服务器代码:

#include <stdio.h>
#include <sys/un.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <errno.h>
#include<syslog.h>

#define SV_SOCK_PATH "/tmp/rtig.sock"    //path to be used by socket
#define BUF_SIZE 256    //Max length of string listened to
#define BACKLOG 5

int main(int argc, char *argv[]){
  struct sockaddr_un addr;
  int sfd, cfd;        //File Descriptors for the server and the client
  ssize_t numRead;    //Length of the string read from the client.
  u_int8_t buf[BUF_SIZE];    //String that reads messages
  char plain[BUF_SIZE];    //Plain string for writing to the log
  memset(plain, 0, sizeof plain); //blank out plain string

  openlog(argv[0], LOG_CONS | LOG_PID | LOG_NDELAY, LOG_LOCAL1); //Write the messages to the syslog

//---Declare socket--------------------------------------
  sfd = socket(AF_UNIX, SOCK_STREAM, 0);
  if(sfd!=0){
    syslog(LOG_INFO, "socket success");
  }
  else{
    syslog(LOG_INFO, "socket unsuccessful");
  }

  //--Test to see if there's already a socket at SV_SOCK_PATH, and remove it if there is.
  if (remove(SV_SOCK_PATH) == -1 && errno !=ENOENT){
    syslog(LOG_INFO, "error removing socket");
  }

 //-----------------------------------------------------------

  //--blank out the socket address, then write the information to it
  memset(&addr, 0, sizeof(struct sockaddr_un));
  addr.sun_family = AF_UNIX;
  strncpy(addr.sun_path, SV_SOCK_PATH, sizeof(addr.sun_path)-1); //ensure path is null terminated

//----Bind the socket to the address-------------------------------------
  if (bind(sfd, (struct sockaddr *) &addr, sizeof(struct sockaddr_un))!=0){
    syslog(LOG_INFO, "bind unsuccessful");
  }
  else{
    syslog(LOG_INFO, "bind successful");
  }
//------------------------------------------------------------------------

//-----Listen on the socket-----------------------------------------------
  if (listen(sfd, BACKLOG) != 0){
    syslog(LOG_INFO, "listen failed");
  }
  else{
    syslog(LOG_INFO, "listen succeeded");
  }
//-------------------------------------------------------------------------

//--------Accept messages on the socket------------------------------------
 socklen_t csize; 

  while(1){

    cfd = accept(sfd, (struct sockaddr *)&addr,&csize);

    if (cfd < 0) {
      syslog(LOG_INFO, "accept failed: %s", strerror(errno));
    }

    while ( (numRead=read(cfd, buf, BUF_SIZE)) > 0 ){ 

    dump_packet(buf, numRead);

    }

  }
 //-------------------------------------------------------------------------

//---code never gets here but this is how to close the log and the socket--
  closelog();
  close(cfd);
}

以下是从我的应用程序连接到此服务器的客户端的简单版本:

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>

#define SV_SOCK_PATH "/tmp/rtig.sock"   //path to be used by socket
#define BACKLOG 5

int isDaemon = 1;

void etmlog(int level, char *message)
{
isDaemon == 1 ? syslog(level, message) : printf(message);
}

int main(){
    struct sockaddr_un addr;
    unsigned int sockfd;
    ssize_t numRead;


if ((sockfd = socket(AF_UNIX, SOCK_STREAM, 0)) > 0) {
    etmlog(LOG_INFO, "Socket Opened\n");
}
    else {
    etmlog(LOG_ERR, "Socket Failed:\n");
    etmlog(LOG_ERR, strerror(errno));
    exit(-1);
}

memset(&addr, 0, sizeof(struct sockaddr_un));
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, SV_SOCK_PATH, sizeof(addr.sun_path) - 1);    // -1 ensures null terminated string

if (connect
    (sockfd, (struct sockaddr *)&addr,
     sizeof(struct sockaddr_un)) == -1) {
    etmlog(LOG_ERR, "Socket Failed\n");
    etmlog(LOG_ERR, strerror(errno));
    exit(1);
} else {
    etmlog(LOG_INFO, "Socket Connection Successful\n");
}

    while (1){
     // some data is read into buf up here

        if (write(sockfd, buf, rdlen) < 0) {
        etmlog(LOG_ERR, "Write to Socket Failed:");
        etmlog(LOG_ERR, strerror(errno));
        }
    }

   close(sockfd);
   return 0;
 }

我很欣赏我刚刚发布了大量的代码供您阅读,但如果有人能给我一些指示,我将非常感激。

1 个答案:

答案 0 :(得分:5)

您没有正确使用accept。必须将第三个参数初始化为第二个参数的大小,以便accept不会溢出它。请参阅man accept