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

标签 c sockets unix unix-socket

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

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

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

我很感激我刚刚发布了很多代码来通读,但如果有人能给我一些建议,我将不胜感激。

最佳答案

您没有正确使用accept。第三个参数必须初始化为第二个参数的大小,这样 accept 就不会溢出它。参见 man accept

关于c - 嵌入式设备上的 Unix 域套接字代码失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20332780/

相关文章:

c - printf:格式 -Wformat 中的未知转换类型字符 ')'

c - RS-232 串行合并

javascript - fns[i](套接字,函数(错误){ TypeError : Property '0' of object [object Object] is not a function in/socket. io/lib/namespace.js:119

c - UDP 套接字使用 select()

unix - 命令行获取进程使用的内存

c - 调用内核次数过多时程序停止工作

将字符串复制到另一个 C

C++ CreateThread 不显示结果

linux - 按列排序 Unix

linux - AWK 根据另一个文件的列过滤一个文件