我在使用带有AF_UNIX套接字的asyncore时遇到了一些问题.这段代码
import asyncore, socket, os
class testselect(asyncore.dispatcher):
path = '/tmp/mysocket'
def __init__(self):
asyncore.dispatcher.__init__(self)
self.create_socket(socket.AF_UNIX, socket.SOCK_DGRAM)
self.bind(self.path)
self.buffer = 'buffer'
def handle_connect(self):
print 'handle_connect'
pass
def handle_close(self):
print 'handle_close'
if os.path.exists(self.path)
os.remove(self.path)
self.close()
def handle_read(self):
print 'handle_read'
print self.recv(8192)
def writable(self):
print 'writable'
return (len(self.buffer) > 0)
def handle_write(self):
print 'handle_write'
sent = self.send(self.buffer)
self.buffer = self.buffer[sent:]
client = testselect()
asyncore.loop()
Run Code Online (Sandbox Code Playgroud)
如果我执行代码
$ python select_prova.py
writable
handle_connect
handle_write
handle_close
$
Run Code Online (Sandbox Code Playgroud)
它立即退出,不等待读写.如果我改变代码以强制writable()方法总是返回False,它正确地等待输入,我可以像这样与socat通信
$ socat readline UNIX:/tmp/mysocket
Run Code Online (Sandbox Code Playgroud)
但只是为了阅读(逻辑上写不起作用,因为writable()返回False).我的代码中是否有错误,或者我无法使用asyncore/select()管理AF_UNIX套接字?
我设置了客户端/服务器,我希望我的客户端知道服务器是否已接受连接。否则我的客户不知道它仍在等待被接受。我不能依赖进一步的通信(协议规范)来验证这一点。因此,例如,从服务器向客户端发送“Good to go”字符串就不是一个选项。是否有一个标志或其他东西可以让我检查服务器是否确实正在接收?一些示例代码如下:
/* Client */
...
getaddrinfo(ip, port, &hints, &servinfo);
connect(sockfd, info->ai_addr, info->ai_addrlen);
if (info == NULL) {
printf("connection failure\n");
exit(1);
}
inet_ntop(info->ai_family, get_in_addr((struct sockaddr *)info->ai_addr), ipstring, sizeof(ipstring));
printf("Connected to %s!\n", ipstring);
...
/* Server */
...
pause(); /* If don't accept the connection, how to make the client know? */
new_fd = accept(sockfd, (struct sockaddr *)&cli_addr, &addr_size);
...
Run Code Online (Sandbox Code Playgroud) 我有一个 PHP 客户端通过纯文本 Unix 域套接字连接到本地 C 服务器程序。但是,我可以让它很好地关闭的唯一方法是,如果我使用以下命令完成套接字会话:
stream_socket_shutdown($sock, 1); // shutdown socket writing
usleep(500 * 1000); // wait for 0.5 seconds
fclose($sock); // actually close the socket (finally)
Run Code Online (Sandbox Code Playgroud)
我想像我的 C 客户端一样优雅地关闭它:-
shutdown(connection_fd, SHUT_WR); // tell server we've stopped sending queries
// Read from the socket until poll(connection_fd) yields POLLRDHUP / POLLHUP / POLLERR / POLLNVAL
shutdown(connection_fd, SHUT_RDWR); // tell connection we've stopped listening
close(connection_fd); // close the whole connection (finally)
Run Code Online (Sandbox Code Playgroud)
但是,PHP 似乎没有直接的 socket poll() 等效项。如何让 PHP 优雅地关闭我的本地套接字?
事情是这样的,我正在用 C 语言(使用 unix 系统调用)编写一个简单的 tcp 套接字服务器,但我无法接受连接。
据我所知,我很好地完成了服务器初始化,但是当我尝试连接到我打印出来的端口(参见下面的代码)时,它拒绝了,就好像什么都没有一样。
更重要的是,当我 netstat 时,该端口甚至没有在使用中。我不会在当前的设置中抛出任何错误,我已经没有想法了。
int main(){
int sock_fd;
int conn_fd;
struct sockaddr_in serv_addr;
struct sockaddr_in cli_addr;
socklen_t* serlen;
socklen_t* clilen;
clilen = malloc(sizeof(socklen_t));
serlen = malloc(sizeof(socklen_t));
*serlen = sizeof(serv_addr);
*clilen = sizeof(cli_addr);
/*=============================Create Socket=============================*/
//Create Socket
sock_fd = socket(AF_INET, SOCK_STREAM, 0);
if(sock_fd<0){
fprintf(stderr,"error creating socket\n");
exit(1);}
//Initialize Server Address Struct
bzero((char *) &serv_addr, *serlen);
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = 0;
/*=============================Bind Address==============================*/
//Bind socket to an address
if(bind(sock_fd,(struct sockaddr*)&serv_addr,*serlen)<0){
fprintf(stderr,"error …Run Code Online (Sandbox Code Playgroud) 客户端必须向服务器发送 2 个字符串,服务器必须向客户端发回一个字符串,并且并行处理客户端。这两个实体在 Unix 下使用数据报交换数据。我的问题是,当我使用线程时,我无法将数据发送回客户端,也无法读取数据。此外,即使我不使用线程,我也无法将消息正确发送回客户端。
\n\n服务器是:
\n\n#include <sys/socket.h>\n#include <netinet/in.h>\n#include <pthread.h>\n#include <stdio.h>\n#include <string.h>\n#include <stdint.h>\n#include <signal.h>\n#include <unistd.h>\n#include <stdlib.h>\n\n\nint sd = 0;\nvoid* worker(void* argm) {\n struct sockaddr_in* adress = (struct sockaddr_in*) argm;\n char s[100],s2[100];\n int adressLen;\n\n recvfrom(sd, s, sizeof(s), 0, (struct sockaddr*) &adress, &adressLen);\n perror("recv");\nRun Code Online (Sandbox Code Playgroud)\n\nPerror显示recv:非套接字上的套接字操作
\n\n printf("I received: %s\\n",s);\n\n strcat(s2,"sample");\n s2[strlen(s2)]=\'\\0\';\n sendto(sd, &s2, sizeof(s2), 0, (struct sockaddr*) &adress,sizeof(adress));\n perror("send");\n\n}\nRun Code Online (Sandbox Code Playgroud)\n\n最后perror()显示发送:非套接字上的套接字操作。\n这也会导致客户端无限等待来自服务器的字符串。
int main(int argc, char* argv[]) {\n int sd;\n int servPort;\n\n struct sockaddr_in servAddr; \n\n if …Run Code Online (Sandbox Code Playgroud) 我正在开发一个大型 Mac 应用程序,该应用程序分为许多不同进程中的许多组件。其中一个组件是 Safari Extension Companion[1],它是一种“应用程序扩展”,允许基于 JavaScript 的扩展与本机代码对话(这是我们组件之间安全 IPC 所必需的)。IPC 通道是用户~/Library/Application Support/<APPNAME>/目录中的 Unix 域套接字。出于遗留原因,Unix 套接字服务器使用 HTTP,客户端库使用自定义URLProtocol,以防万一。
这适用于我们所有其他组件,但它们都没有在沙箱中运行[2]。但是,扩展伴侣的 Xcode 模板创建了一个沙箱,并且如果是沙箱,则伴侣会加载,但它似乎需要沙箱。我尝试在权利文件中设置com.apple.security.app-sandbox为false,或删除权利文件(以及对它的所有引用),两者似乎都阻止了 Safari 加载伴侣(如果直接调用它仍然作为自己的二进制文件运行,但 Safari 显然赢了) t 触摸它)。
我已经向沙箱添加了例外,以允许它访问相关目录,并且直接访问 IPC 套接字;但这似乎还不够。尝试打开套接字时遇到的错误是EPERM(不允许操作),这并不能真正解释问题。在向权利添加例外并修复路径后,~/Library/现在可以按预期写入日志文件(也在 "real" 下)之类的内容。
此错误发生在connect调用套接字时(它返回 -1,表示错误,并且errno为 1 ( EPERM)),因此实际上从未尝试写入或读取套接字。这对我来说似乎很奇怪,因为 - 根据Apple Sandbox Design Guide -
UNIX 域套接字很简单;它们就像任何其他文件一样工作
关于沙盒例外。
权利文件(使用此处的答案从自动生成的模板中修改:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict> …Run Code Online (Sandbox Code Playgroud) 由于 X 是服务器,因此我有一种方法可以通过套接字监听 X 事件,而不是使用XNextEvent?
我有一个程序,通过在主线程中运行的循环中调用来监视系统epoll事件epoll_wait。由于我无法弄清楚如何通过文件描述符侦听 X 事件,因此我不得不XNextEvent在单独的线程中运行专用循环,并在事件发生时调用的函数的调用周围放置互斥体。
如果有人好奇的话,这是我编写的用于轮询 X 事件的函数。目前我只监听与键盘布局切换相关的事件。
void* xevent_loop(void*) {
int xkbEventType;
XkbQueryExtension(dpy, 0, &xkbEventType, 0, 0, 0);
XkbSelectEventDetails(dpy,
XkbUseCoreKbd, XkbStateNotify, XkbAllStateComponentsMask,
XkbGroupStateMask);
XSync(dpy, False);
for (XEvent e;;) {
XNextEvent(dpy, &e);
if (e.type == xkbEventType) {
XkbEvent* xkbe = (XkbEvent*) &e;
if (xkbe->any.xkb_type == XkbStateNotify) {
pthread_mutex_lock(&setroot_mutex);
fmt_kbd_layout(xkbe->state.group);
setroot();
pthread_mutex_unlock(&setroot_mutex);
}
}
}
return NULL;
}
Run Code Online (Sandbox Code Playgroud) 我很好奇是否可以将UNIX套接字映射到INET套接字.情况很简单,我想连接到MySQL服务器.不幸的是它禁用了INET套接字,因此我只能连接UNIX套接字.我正在使用/写入的工具必须连接在INET套接字上,所以我试图看看是否可以将一个映射到另一个.
这需要相当多的搜索,但我确实找到了socat,据说它正在寻找我正在寻找的东西.我想知道是否有人对如何实现这一点有任何建议.我一直在使用的命令行(部分成功)是:
socat -v UNIX-CONNECT:/var/lib/mysql/mysql.sock TCP-LISTEN:6666,reuseaddr
Run Code Online (Sandbox Code Playgroud)
现在我可以建立连接并与服务器通信.不幸的是,任何尝试进行多个连接都会失败,因为我需要使用fork选项,但是这个选项似乎使连接无法正常运行.
我知道我可以用Perl(我的首选语言)来解决这个问题,但我宁愿避免自己编写整个实现.我熟悉IO :: Socket库,我只是希望有人有这方面的经验.对建议/想法持开放态度.
谢谢.
我没有得到的是Unix域套接字之间的数据流.
我理解Unix Domain Socket的数据流是
LocalSocket client .connect() - > LocalServerSocket server .accept()
客户端将数据发送到服务器,直到我理解.
然而,对于来自Android的MediaRecorder的流式视频/音频,经过大量研究后,我看到每个使用LocalSocket代替MediaRecorder文件的例子原则如下:
https://static.foxdogstudios.com/static/presentations/keeping-it-real-time.html#/9
LocalServerSocket server = new LocalServerSocket("some name");
receiver = new LocalSocket();
receiver.connect(server.getLocalSocketAddress());
LocalSocket sender = server.accept();//LocalSocket not LocalServerSocket as in Source link
// ...
// Give the MediaRecorder our fake file
recorder.setOutputFile(sender.getFileDescriptor());
Run Code Online (Sandbox Code Playgroud)
此代码如下所示:
MediaRecorder- > LocalSocket sender- >
LocalServerSocket server .accept() - > LocalSocket receiver .connect()
到底是怎么回事??
显然,套接字数据以相反的方向流动,因此,我不明白为什么这段代码按预期工作.
请你劝告.谢谢.
出于多种原因,我想在两个进程之间使用unix域套接字进行IPC.
每个进程通过写入套接字并将此事件传递给第二个进程来响应来自外部世界的某些特定类型的异步事件 - 同时 - 每个进程还需要读取来自另一个套接字的数据来执行某些操作.实质上,在这个模型中,每个进程将有一个套接字和两个线程:一个用于可能阻塞读取,一个用于写入.
我想知道是否可以使用unix域套接字来独立地从/向每个进程读取和写入,而不使用任何显式锁定,这种安全性将由这些套接字隐式保证.如果是的话,我也想知道这个保证在哪里正式声称.