我认为多个套接字可以与相同的TCP端口相关联.
但同样的事情可以用于UDP吗?
我想在本地向许多应用程序广播消息.为此,我认为UDP套接字是最好的IPC,如果我是狼,请纠正我.
为此,我使用以下代码:
用于广播:
/*
** broadcaster.c -- a datagram "client" that can broadcast
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#define SERVERPORT 4950 // the port users will be connecting to
int main(int argc, char *argv[])
{
int sockfd;
struct sockaddr_in their_addr; // connector's address information
struct hostent *he;
int numbytes;
int broadcast = 1;
//char broadcast = '1'; // if that doesn't work, try this …Run Code Online (Sandbox Code Playgroud) 我在Windows 7中运行两个stunnel实例,配置为侦听同一个端口,看起来它们都在同一端口上成功侦听(只使用socket()/ bind()/ listen()).两个实例似乎都成功通过所有调用,并且它们显示在netstat中:
C:\>netstat -ano | grep 8000
TCP 0.0.0.0:8000 0.0.0.0:0 LISTENING 5828
TCP 0.0.0.0:8000 0.0.0.0:0 LISTENING 5852
Run Code Online (Sandbox Code Playgroud)
第一个要监听的是获取所有传入的请求.
这与我的所有期望完全相反.(我当时希望让EADDRINUSE告诉我港口很忙.)所以....
我对零停机部署系统感兴趣,该系统不使用Elixir/Erlang热升级(由于代码运行时数据迁移的复杂性).
我听说我可以在将服务器绑定到适配器时使用SO_REUSEPORT选项,这样我就可以运行绑定到同一地址和端口的同一应用程序的两个实例.我的意图是在与运行版本1相同的服务器上部署版本2,启动版本2,然后优雅地停止版本1,这应该允许传入连接自然地开始专门连接到版本2.
无论这是否与我的计划完全一致 - 我的意图是测试这种配置,因为它知道它在不同的操作系统上的行为不同 - 我想知道配置Phoenix执行此操作所需的具体步骤,因为这似乎更低 - 内部的级别配置:gen_tcp.
或者,如果有一种方法可以配置OS或Erlang VM以默认启用此选项的所有连接,那就更好了.
我正在用 C 进行一些基本的套接字编程,并且在我尝试运行代码的每台计算机上都遇到了这个错误。代码编译得很好,但是当我尝试运行它时,我收到错误 setsockopt: 协议不可用。这似乎不是一个很常见的错误,但我在每台尝试运行它的计算机上都会遇到它。所有的电脑都是MacOS。
#include <unistd.h>
#include <stdio.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <string.h>
#define PORT 8080
int main(int argc, char const *argv[])
{
int server_fd, new_socket, valread;
struct sockaddr_in address;
int opt = 1;
int addrlen = sizeof(address);
char buffer[1024] = {0};
char *hello = "Hello from server";
// Creating socket file descriptor
if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0)
{
perror("socket failed");
exit(EXIT_FAILURE);
}
// Forcefully attaching socket to the port 8080
if (setsockopt(server_fd, …Run Code Online (Sandbox Code Playgroud) 手册页对这个选项几乎没有任何解释,虽然网络上和 StackOverflow 上的答案中有大量可用信息,但我发现那里提供的许多信息甚至是自相矛盾的。那么该设置的真正用途是什么?为什么我需要设置或更改它?
我目前正在使用C语言从Tru64移植到Linux Suse 11.在Tru64上,他们将SO_SNDLOWATsocket选项的值设置为1024 * 64.在Linux上,此选项不可更改,其值为1.
我想弄清楚,是什么不设置影响SO_SNDLOWAT到1024 * 64在Linux软件执行.
问题是我找到了两个定义(解释)的目的SO_SNDLOWAT:
在Linux上的socket的手册页上找到:
SO_SNDLOWAT指定缓冲区中的最小字节数,直到套接字层将数据传递给协议
我知道它指定缓冲区中要进行的最小字节数(在这种情况下用于发送消息).缓冲区需要至少填充SO_SNDLOWAT字节才能继续
在" UNIX网络编程:W. Richard Stevens的插座网络API,Bill Fenner,Andrew M. Rudoff " 一书中找到
发送低水位标记是套接字发送缓冲区中必须存在的可用空间量,以便选择返回"可写".
我明白了,如果我想在套接字缓冲区中写入(无论我写的是什么大小),缓冲区需要有最少的SO_SNDLOWAT字节空闲.
我不知道该怎么做SO_SNDLOWAT.
我的python测试代码:
import socket
s1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s1.bind(('192.168.1.1', 80))
s1.listen(5)
s2 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s2.bind(('0.0.0.0', 80))
s2.listen(5)
Run Code Online (Sandbox Code Playgroud)
我收到了这个错误:
fpemud-workstation test # ./test.py
Traceback (most recent call last):
File "./test.py", line 11, in <module>
s2.bind(('0.0.0.0', 80))
File "/usr/lib64/python2.7/socket.py", line 224, in meth
return getattr(self._sock,name)(*args)
socket.error: [Errno 98] Address already in use
Run Code Online (Sandbox Code Playgroud)
192.168.1.1是我的eth0接口的ip地址.
我认为0.0.0.0:80和192.168.1.1:80应该能够共存.
带有dst-addr 192.168.1.1的数据包进入套接字s1,带有其他dst-addr的数据包进入套接字s2.
Linux内核> = 3.9允许通过设置在内核负载平衡的进程之间共享套接字SO_REUSEPORT:http://lwn.net/Articles/542629/
如何将它用于类型的套接字AF_UNIX?
看来,它只适用于TCP,而不适用于Unix域套接字.
这是一个Python测试程序:
import os
import socket
if not hasattr(socket, 'SO_REUSEPORT'):
socket.SO_REUSEPORT = 15
if True:
# using TCP sockets
# works. test with: "echo data | nc localhost 8888"
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
s.bind(('', 8888))
else:
# using Unix domain sockets
# does NOT work. test with: "echo data | nc -U /tmp/socket1"
s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
try:
os.unlink("/tmp/socket1")
except:
pass
s.bind("/tmp/socket1")
s.listen(1) …Run Code Online (Sandbox Code Playgroud) 在旧版本的Mac OS X中,通配符绑定的工作方式如下所述:
套接字选项SO_REUSEADDR和SO_REUSEPORT,它们有何不同?它们在所有主要操作系统中的含义是否相同?
组播地址
SO_REUSEADDR的含义会更改多播地址,因为它允许多个套接字绑定到源多播地址和端口的完全相同的组合.换句话说,对于多播地址,SO_REUSEADDR的行为与单播地址的SO_REUSEPORT完全相同.实际上,代码对于多播地址同样对待SO_REUSEADDR和SO_REUSEPORT,这意味着您可以说SO_REUSEADDR对所有多播地址都意味着SO_REUSEPORT,反之亦然.
和
MacOS X.
在其核心,MacOS X只是一个BSD风格的UNIX,基于BSD代码的相当晚的分支,甚至与Mac OS 10.3版本的FreeBSD 5同步.这就是为什么MacOS X提供与BSD相同的选项,它们的行为方式与BSD相同.
但在10.10.5中,我在测试网络库时发现了一个变化.
即使设置了SO_REUSEADDR,两个未绑定(通配符)UDP套接字也不能再共享同一个端口(errno = EADDRINUSE).必须在两者上设置SO_REUSEPORT,这对我来说是一个谜.
它可以通过这个简单的测试代码重现:
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
int main() {
for(int p = 0; p < 4; ++p) {
printf("Flags set: ");
if(p&1) printf("SO_REUSEADDR ");
if(p&2) printf("SO_REUSEPORT");
printf("\n");
int handles[2];
bool success = true;
for(int i = 0; i < sizeof(handles)/sizeof(int); ++i) {
handles[i] = socket(AF_INET, SOCK_DGRAM, 0);
int flag = 1;
if((p&1) …Run Code Online (Sandbox Code Playgroud)