我用 C 编写了一个 TCP 套接字,它需要与通过本地网络连接到此地址的移动应用程序一起使用:“device1.local:6666”。
我找到的每个使用 inet_pton() 设置服务器地址的示例都有一个如下所示的 IPV4 地址:192.168.1.34,或者一个 IPV6 地址看起来像这样:2001:db8:8714:3a90::12。如果我希望我的客户端远程登录到“device1.local”而不是数字或十六进制地址,我应该指定哪种格式?如何设置我的 TCP 套接字服务器来响应该地址?
这行不通:
local_socket = socket(AF_INET6, SOCK_STREAM, 0);
if(local_socket < 0) {
printf("unable to create socket\n");
return false;
}
printf("socket created\n");
bzero((void *)&server_address, sizeof(server_address));
server_address.sin6_family = AF_INET6;
int s_code = inet_pton(AF_INET6, "device1.local", &server_address.sin6_addr);
server_address.sin6_port = htons(port_number);
printf("inet_pton returned: %d\n", s_code);
char str[INET6_ADDRSTRLEN];
inet_ntop(AF_INET6, &server_address.sin6_addr, str, INET6_ADDRSTRLEN);
printf("address from inet_ntop(): %s\n", str);
这是输出:
socket created
inet_pton returned: 0
address from inet_ntop(): ::
我意识到我可能对互联网(或本地网络)的工作原理缺乏基本的了解。如果您能给我任何相关链接,以便我可以了解有关自定义文本地址如何工作的更多信息,我们将不胜感激。
最佳答案
Which format do I specify if I want my client to telnet to "device1.local" instead of a numeric or hex address?
inet_pton() 将 IP 地址的文本表示形式转换为其二进制格式(in_addr 用于 IPv4,in6_addr 用于 IPv6,等等) .您不能使用它来将主机名解析为 IP 地址。为此,您需要使用 gethostbyname()(已弃用)或 getaddrinfo()(首选)。
这是一个 gethostbyname() 示例:
int connect_to_addr(const sockaddr *addr, int addrlen)
{
local_socket = socket(addr->sa_family, SOCK_STREAM, IPPROTO_TCP);
if (local_socket == -1)
{
printf("unable to create socket\n");
return -1;
}
char str[INET6_ADDRSTRLEN];
unsigned short port;
switch (addr->sa_family)
{
case AF_INET:
{
struct sockaddr_in *saddr = (struct sockaddr_in*)addr;
inet_ntop(AF_INET, &(saddr->sin6_addr), str, sizeof(str));
port = ntohs(saddr->sin_port);
break;
}
case AF_INET6:
{
struct sockaddr_in6 *saddr = (struct sockaddr_in6*)addr;
inet_ntop(AF_INET6, &(saddr->sin6_addr), str, sizeof(str));
port = ntohs(saddr->sin6_port);
break;
}
}
printf("connecting to address: %s on port: %hu\n", str, port);
if (connect(local_socket, addr, addrlen) != 0)
{
printf("unable to connect\n");
close(local_socket);
local_socket = -1;
return 0;
}
printf("connected\n");
return 1;
}
bool connect_to_host(const char *hostname, unsigned short port_number)
{
local_socket = -1;
sockaddr_storage server_address;
bzero(&server_address, sizeof(server_address));
if (inet_pton(AF_INET6, hostname, &(((struct sockaddr_in6*)&server_address)->sin6_addr)) == 1)
{
struct sockaddr_in6 *saddr = (struct sockaddr_in6*)&server_address;
saddr->sin6_family = AF_INET6;
saddr->sin6_port = htons(port_number);
if (connect_to_addr((struct sockaddr*)saddr, sizeof(*saddr)) != 1)
return false;
}
else if (inet_pton(AF_INET, hostname, &(((struct sockaddr_in*)&server_address)->sin_addr)) == 1)
{
struct sockaddr_in *saddr = (struct sockaddr_in*)&server_address;
saddr->sin_family = AF_INET;
saddr->sin_port = htons(port_number);
if (connect_to_addr((struct sockaddr*)saddr, sizeof(*saddr)) != 1)
return false;
}
else
{
printf("resolving %s\n", hostname);
struct hostent *host = gethostbyname(hostname);
if (!host)
{
printf("unable to resolve\n");
return false;
}
switch (host->h_addrtype)
{
case AF_INET:
case AF_INET6:
break;
default:
printf("resolved host type is not supported\n");
return false;
}
for(char **addr = host->h_addr_list; *addr != 0; ++addr)
{
bzero(&server_address, sizeof(server_address));
int addrlen;
switch (host->h_addrtype)
{
case AF_INET:
{
struct sockaddr_in *saddr = (struct sockaddr_in*)&server_address;
saddr->sin_family = AF_INET;
bcopy(*addr, &(saddr->sin_addr), host->h_length);
saddr->sin_port = htons(port_number);
addrlen = sizeof(*saddr);
break;
}
case AF_INET6:
{
struct sockaddr_in6 *saddr = (struct sockaddr_in6*)&server_address;
saddr->sin6_family = AF_INET6;
bcopy(*addr, &(saddr->sin6_addr), host->h_length);
saddr->sin6_port = htons(port_number);
addrlen = sizeof(*saddr);
break;
}
}
if (connect_to_addr((struct sockaddr*)&server_address, addrlen) != 0)
break;
}
}
return (local_socket != -1);
}
if (connect_to_host("device.local", 6666))
{
// use local_socket as needed...
close(local_socket);
}
这是一个 getaddrinfo() 示例:
int connect_to_addr(const sockaddr *addr, int addrlen)
{
local_socket = socket(addr->sa_family, SOCK_STREAM, IPPROTO_TCP);
if (local_socket == -1)
{
printf("unable to create socket\n");
return -1;
}
char str[INET6_ADDRSTRLEN];
unsigned short port;
switch (addr->sa_family)
{
case AF_INET:
{
struct sockaddr_in *saddr = (struct sockaddr_in*)addr;
inet_ntop(AF_INET, &(saddr->sin6_addr), str, sizeof(str));
port = ntohs(saddr->sin_port);
break;
}
case AF_INET6:
{
struct sockaddr_in6 *saddr = (struct sockaddr_in6*)addr;
inet_ntop(AF_INET6, &(saddr->sin6_addr), str, sizeof(str));
port = ntohs(saddr->sin6_port);
break;
}
}
printf("connecting to address: %s on port: %hu\n", str, port);
if (connect(local_socket, addr, addrlen) != 0)
{
printf("unable to connect\n");
close(local_socket);
local_socket = -1;
return 0;
}
printf("connected\n");
return 1;
}
bool connect_to_host(const char* hostname, unsigned short port)
{
local_socket = -1;
printf("resolving %s:%hu\n", hostname, port);
struct addrinfo hints;
bzero((void *)&hints, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
char service[6];
bzero(service, sizeof(service));
sprintf(service, "%hu", port_number);
struct addrinfo *addrs = 0;
if (getaddrinfo(hostname, service, &hints, &addrs) != 0)
{
printf("unable to resolve\n");
return false;
}
for(struct addrinfo *addr = addrs; addr != 0; addr = addr->ai_next)
{
if (connect_to_addr((struct sockaddr*)(addr->ai_sockaddr), addr->ai_addrlen) != 0)
break;
}
freeaddrinfo(addrs);
return (local_socket != -1);
}
if (connect_to_host("device.local", 6666))
{
// use local_socket as needed...
close(local_socket);
}
How do I set up my TCP socket server to answer that address?
您只需将您的监听套接字bind() 到服务器机器本地的特定 IP 地址(使用 getifaddrs() 或等效的 API 获取列表本地 IP)。或者使用通配符地址(INADDR_ANY 用于 IPv4,in6addr_any 用于 IPv6)绑定(bind)到所有可用的本地 IP。
客户端的 DNS 查找将负责将 device.local 解析为路由到您的服务器计算机的 IP 地址,如果您的服务器套接字正在监听该 IP,那么它可以 accept() 传入连接。
关于我可以使用 inet_pton 为我的 TCP 套接字服务器设置文本地址,例如 "device1.local"吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38796549/
我正在尝试使用ruby和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我
我正在尝试测试是否存在表单。我是Rails新手。我的new.html.erb_spec.rb文件的内容是:require'spec_helper'describe"messages/new.html.erb"doit"shouldrendertheform"dorender'/messages/new.html.erb'reponse.shouldhave_form_putting_to(@message)with_submit_buttonendendView本身,new.html.erb,有代码:当我运行rspec时,它失败了:1)messages/new.html.erbshou
我在从html页面生成PDF时遇到问题。我正在使用PDFkit。在安装它的过程中,我注意到我需要wkhtmltopdf。所以我也安装了它。我做了PDFkit的文档所说的一切......现在我在尝试加载PDF时遇到了这个错误。这里是错误:commandfailed:"/usr/local/bin/wkhtmltopdf""--margin-right""0.75in""--page-size""Letter""--margin-top""0.75in""--margin-bottom""0.75in""--encoding""UTF-8""--margin-left""0.75in""-
我想安装一个带有一些身份验证的私有(private)Rubygem服务器。我希望能够使用公共(public)Ubuntu服务器托管内部gem。我读到了http://docs.rubygems.org/read/chapter/18.但是那个没有身份验证-如我所见。然后我读到了https://github.com/cwninja/geminabox.但是当我使用基本身份验证(他们在他们的Wiki中有)时,它会提示从我的服务器获取源。所以。如何制作带有身份验证的私有(private)Rubygem服务器?这是不可能的吗?谢谢。编辑:Geminabox问题。我尝试“捆绑”以安装新的gem..
我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h
为了将Cucumber用于命令行脚本,我按照提供的说明安装了arubagem。它在我的Gemfile中,我可以验证是否安装了正确的版本并且我已经包含了require'aruba/cucumber'在'features/env.rb'中为了确保它能正常工作,我写了以下场景:@announceScenario:Testingcucumber/arubaGivenablankslateThentheoutputfrom"ls-la"shouldcontain"drw"假设事情应该失败。它确实失败了,但失败的原因是错误的:@announceScenario:Testingcucumber/ar
最近,当我启动我的Rails服务器时,我收到了一长串警告。虽然它不影响我的应用程序,但我想知道如何解决这些警告。我的估计是imagemagick以某种方式被调用了两次?当我在警告前后检查我的git日志时。我想知道如何解决这个问题。-bcrypt-ruby(3.1.2)-better_errors(1.0.1)+bcrypt(3.1.7)+bcrypt-ruby(3.1.5)-bcrypt(>=3.1.3)+better_errors(1.1.0)bcrypt和imagemagick有关系吗?/Users/rbchris/.rbenv/versions/2.0.0-p247/lib/ru
在Rails4.0.2中,我使用s3_direct_upload和aws-sdkgems直接为s3存储桶上传文件。在开发环境中它工作正常,但在生产环境中它会抛出如下错误,ActionView::Template::Error(noimplicitconversionofnilintoString)在View中,create_cv_url,:id=>"s3_uploader",:key=>"cv_uploads/{unique_id}/${filename}",:key_starts_with=>"cv_uploads/",:callback_param=>"cv[direct_uplo
我遵循MichaelHartl的“RubyonRails教程:学习Web开发”,并创建了检查用户名和电子邮件长度有效性的测试(名称最多50个字符,电子邮件最多255个字符)。test/helpers/application_helper_test.rb的内容是:require'test_helper'classApplicationHelperTest在运行bundleexecraketest时,所有测试都通过了,但我看到以下消息在最后被标记为错误:ERROR["test_full_title_helper",ApplicationHelperTest,1.820016791]test
我正在尝试从Postgresql表(table1)中获取数据,该表由另一个相关表(property)的字段(table2)过滤。在纯SQL中,我会这样编写查询:SELECT*FROMtable1JOINtable2USING(table2_id)WHEREtable2.propertyLIKE'query%'这工作正常:scope:my_scope,->(query){includes(:table2).where("table2.property":query)}但我真正需要的是使用LIKE运算符进行过滤,而不是严格相等。然而,这是行不通的:scope:my_scope,->(que