加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > Linux > 正文

linux上的unix域套接字?

发布时间:2020-12-14 01:03:49 所属栏目:Linux 来源:网络整理
导读:来自 http://www.thomasstover.com/uds.html的以下unix域套接字客户端和服务器示例在我的slackware linux框中无法正常工作.我得到这个输出: $./server1 $$./client1 MESSAGE FROM SERVER: hello from a client 我希望服务器从客户端和客户端打印消息hello以
来自 http://www.thomasstover.com/uds.html的以下unix域套接字客户端和服务器示例在我的slackware linux框中无法正常工作.我得到这个输出:

$./server1 
$

$./client1 
MESSAGE FROM SERVER: hello from a client

我希望服务器从客户端和客户端打印消息hello以从服务器打印hello.

我的操作系统和编译器如下:

$uname -a                                                                                                    
Linux temeraire 2.6.37.6-smp #2 SMP Sat Apr 9 23:39:07 CDT 2011 i686 Intel(R) Xeon(R) CPU           E3110  @ 3.00GHz Ge
nuineIntel GNU/Linux
$gcc -v
Reading specs from /usr/lib/gcc/i486-slackware-linux/4.5.2/specs
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/libexec/gcc/i486-slackware-linux/4.5.2/lto-wrapper
Target: i486-slackware-linux
Configured with: ../gcc-4.5.2/configure --prefix=/usr --libdir=/usr/lib --mandir=/usr/man --infodir=/usr/info --enable-
shared --enable-bootstrap --enable-languages=ada,c,c++,fortran,java,objc,lto --enable-threads=posix --enable-checking=r
elease --with-system-zlib --with-python-dir=/lib/python2.6/site-packages --disable-libunwind-exceptions --enable-__cxa_
atexit --enable-libssp --enable-lto --with-gnu-ld --verbose --with-arch=i486 --target=i486-slackware-linux --build=i486
-slackware-linux --host=i486-slackware-linux
Thread model: posix
gcc version 4.5.2 (GCC)

server.c:

#include <stdio.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>

int connection_handler(int connection_fd)
{
 int nbytes;
 char buffer[256];

 nbytes = read(connection_fd,buffer,256);
 buffer[nbytes] = 0;

 printf("MESSAGE FROM CLIENT: %sn",buffer);
 nbytes = snprintf(buffer,256,"hello from the server");
 write(connection_fd,nbytes);

 close(connection_fd);
 return 0;
}

int main(void)
{
 struct sockaddr_un address;
 int socket_fd,connection_fd;
 socklen_t address_length;
 pid_t child;

 socket_fd = socket(PF_UNIX,SOCK_STREAM,0);
 if(socket_fd < 0)
 {
  printf("socket() failedn");
  return 1;
 } 

 unlink("./demo_socket");

 /* start with a clean address structure */
 memset(&address,sizeof(struct sockaddr_un));

 address.sun_family = AF_UNIX;
 snprintf(address.sun_path,UNIX_PATH_MAX,"./demo_socket");

 if(bind(socket_fd,(struct sockaddr *) &address,sizeof(struct sockaddr_un)) != 0)
 {
  printf("bind() failedn");
  return 1;
 }

 if(listen(socket_fd,5) != 0)
 {
  printf("listen() failedn");
  return 1;
 }

 while((connection_fd = accept(socket_fd,&address_length)) > -1)
 {
  child = fork();
  if(child == 0)
  {
   /* now inside newly created connection handling process */
   return connection_handler(connection_fd);
  }

  /* still inside server process */
  close(connection_fd);
 }

 close(socket_fd);
 unlink("./demo_socket");
 return 0;
}

client.c:

#include <stdio.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#include <string.h>

int main(void)
{
 struct sockaddr_un address;
 int  socket_fd,nbytes;
 char buffer[256];

 socket_fd = socket(PF_UNIX,0);
 if(socket_fd < 0)
 {
  printf("socket() failedn");
  return 1;
 }

 /* start with a clean address structure */
 memset(&address,"./demo_socket");

 if(connect(socket_fd,sizeof(struct sockaddr_un)) != 0)
 {
  printf("connect() failedn");
  return 1;
 }

 nbytes = snprintf(buffer,"hello from a client");
 write(socket_fd,nbytes);

 nbytes = read(socket_fd,256);
 buffer[nbytes] = 0;

 printf("MESSAGE FROM SERVER: %sn",buffer);

 close(socket_fd);

 return 0;
}

解决方法

作为 Dietrich Epp mentioned,您无法初始化在服务器代码中传递给accept的address_length参数.根据 man page,这个参数既是输入参数又是输出参数:在输入时,你告诉它你的地址结构有多大(这样它就知道在告诉你连接客户端的地址时不要写出超出界限的内存),在输出上它告诉你实际上有多大的地址.

要解决此问题,请在调用accept之前将address_length初始化为sizeof(地址).您还应该为每个要接受的调用执行此操作,因为可以修改变量.例如:

while(1)
{
  address_length = sizeof(address);
  if((connection_fd = accept(...,&address_length)) == -1)
  {
    printf("accept error: %sn",strerror(errno));
    break;
  }
  ...
}

我能够重现你的问题是显式地将address_length初始化为无效的值(sockaddr_t)-1,这导致接受失败并出现EINVAL错误(无效参数),但奇怪的是它在客户端尝试连接之后才失败.当客户端尝试连接时,它实际上已成功,但是当它尝试写入套接字时,ECONNRESET失败(“通过对等方重置连接”).

另一个关键点是,您应该始终检查您的返回值.在处理套接字代码时,存在很多失败点,因此迂腐是值得的.如果系统调用失败,它将返回-1并将errno设置为适当的值.您可以使用strerror function将错误代码转换为人类可读的消息,就像我在上面的示例中所做的那样.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读