标签: network-programming

我应该如何构建我的(大多数)基于文本的游戏服务器?

想想MUD/MUCKs,但也许有头像或场所插图.我选择的语言是红宝石.

我需要处理多个持久连接,并在服务器及其各个客户端之间异步传输数据.必须根据客户端会话中发生的活动保持单个数据库的最新状态.每个客户端会话中的活动可能需要立即更新多个其他客户端(用户进入房间;用户向另一个用户发送私人消息).

这是一个目标项目 一个学习项目,所以我的目的是重新发明一两个轮子,以了解有关并发网络编程的更多信息.但是,我对并发和网络编程都不熟悉; 以前我几乎专门在Web应用程序中的非持久性同步HTTP请求的世界中工作.所以,我想确保我重新发明了正确的轮子.

根据emboss的优秀答案,我开始关注某些HTTP服务器的内部情况,因为Web应用程序通常可以避免由于服务器本身抽象问题的彻底解决而导致的线程问题.

我不想使用EventMachine或GServer,因为我还不知道他们做了什么.一旦我对他们的工作方式有了一般意识,他们解决了什么问题以及为什么它们有用,我会对此感到满意.我的目标不是"写游戏",而是"编写游戏并了解一些低级别的东西是如何工作的".我也不清楚某些术语的界限; 例如,"I/O-unbound apps"是"事件驱动的应用程序"的超集吗?反之亦然?

我当然对实现我的目标的一种正确的方式感兴趣,如果它存在,但总体而言我想理解为什么它是正确的方式以及为什么其他方式不太可取.

您可以建议的任何书籍,电子书,在线资源,示例项目或其他花絮都是我真正追求的.

我现在正在做的事情是使用IO#select阻塞连接套接字列表,超时为0.1秒.它将读取的任何信息推送到线程安全的读取队列中,然后无论何时达到超时,它都会从线程安全的写入队列中提取数据.我不确定超时是否应该更短.还有第二个线程轮询套接字处理线程的读取队列并处理"请求".这比我最初的工作方式要好,但仍然可能不太理想.

我在Hacker News上发布了这个问题,并且链接到了我正在处理的一些资源; 类似的东西会很棒:

ruby concurrency network-programming thread-safety mud

18
推荐指数
1
解决办法
1688
查看次数

与SOCK_RAW套接字进行TCP握手

好吧,我意识到这种情况有点不寻常,但我需要建立一个TCP连接(3次握手)只使用原始套接字(在C中,在linux中) - 即我需要自己构建IP头和TCP头.我正在写一个服务器(所以我必须先响应传入的SYN数据包),无论出于什么原因我似乎无法正确使用它.是的,我意识到SOCK_STREAM会为我处理这个,但由于我不想进入的原因,这不是一个选择.

我在网上找到的使用原始套接字的教程都描述了如何构建SYN flooder,但这比实际建立TCP连接要容易一些,因为您不必根据原始数据包构建响应.我已经让SYN flooder示例工作了,我可以从原始套接字读取传入的SYN数据包,但是我仍然无法从客户端创建对传入SYN的有效SYN/ACK响应.

那么,有没有人知道使用原始套接字的好教程不仅仅是创建SYN flooder,还是有人有一些代码可以做到这一点(使用SOCK_RAW,而不是SOCK_STREAM)?我会很感激.


MarkR是绝对正确的 - 问题是内核正在发送重置数据包以响应初始数据包,因为它认为端口已关闭.内核正在击败我的响应并且连接终止.我正在使用tcpdump监视连接 - 我本来应该更加敏锐,并注意到有两个回复,其中一个是重置,搞砸了事情,以及我的程序创建的响应.D'OH!

似乎最有效的解决方案是使用MarkR建议的iptables规则来阻止出站数据包.但是,正如建议的那样,使用标记选项比使用标记选项更容易.我只是匹配是否设置了重置TCP标志.在正常连接过程中,这不太可能是需要的,如果我阻止来自正在使用的端口的所有出站重置数据包,对我的应用程序来说并不重要.这有效地阻止了内核的不需要的响应,但不是我自己的数据包.如果我的程序正在侦听的端口是9999,那么iptables规则如下所示:

iptables -t filter -I OUTPUT -p tcp --sport 9999 --tcp-flags RST RST -j DROP
Run Code Online (Sandbox Code Playgroud)

linux network-programming

17
推荐指数
2
解决办法
1万
查看次数

如何在C中打开和使用套接字?

我想知道用C编程语言打开和写入数据到套接字的最简单,最有效的方法,用于网络编程.

c sockets network-programming

17
推荐指数
3
解决办法
4万
查看次数

HttpURLConnection实现

我已经读过HttpURLConnection支持持久连接,因此可以为多个请求重用连接.我尝试了它,发送第二个POST的唯一方法是第二次调用openConnection.否则我得到一个IllegalStateException("已经连接"); 我使用了以下内容:

try{
URL url = new URL("http://someconection.com");
}
catch(Exception e){}
HttpURLConnection con = (HttpURLConnection) url.openConnection();
//set output, input etc
//send POST
//Receive response
//Read whole response
//close input stream
con.disconnect();//have also tested commenting this out
con = (HttpURLConnection) url.openConnection();
//Send new POST
Run Code Online (Sandbox Code Playgroud)

第二个请求是通过相同的TCP连接发送的(用wireshark验证它)但我无法理解为什么(虽然这是我想要的)因为我已经调用了disconnect.我检查了HttpURLConnection的源代码,并且实现确实保持了对相同目标的连接的keepalive缓存.我的问题是,在发送第一个请求后,我无法看到连接如何放回缓存中.断开连接关闭连接,没有断开连接,我仍然无法看到连接如何放回缓存.我看到缓存有一个run方法来遍历所有空闲连接(我不确定它是如何被调用的),但我找不到连接如何放回缓存中.似乎唯一发生的地方是httpClient的完成方法,但是没有调用带响应的POST.谁可以帮我这个事?

编辑 我的兴趣是,对于tcp连接重用,HttpUrlConnection对象的正确处理是什么.应该关闭输入/输出流,然后是url.openConnection(); 每次发送新请求(避免disconnect())?如果是,我第二次调用url.openConnection()时无法看到连接是如何重用的,因为第一个请求已从缓存中删除了连接,但无法找到返回的连接方式.是否有可能连接没有返回到keepalive缓存(bug?),但操作系统尚未发布tcp连接,在新连接上,OS返回缓冲连接(尚未发布)或类似的东西? EDIT2 我找到的唯一相关内容来自JDK_KeepAlive

...当应用程序在URLConnection.getInputStream()返回的InputStream上调用close()时,JDK的HTTP协议处理程序将尝试清理连接,如果成功,则将连接放入连接缓存以供将来的HTTP请求重用.

但我不确定这是哪个处理程序.sun.net.www.protocol.http.Handler没有做任何缓存,因为我看到谢谢!

java network-programming jdk1.6 httpurlconnection

17
推荐指数
2
解决办法
3万
查看次数

用于C++的套接字API或库?

我最近越来越多地使用C++.我用C做了一些(非常小的)套接字编程,但是对使用C++做一些工作很感兴趣.我只能在基于C的套接字实现上找到参考/教程.是否有一个原因?我知道,或者相信我知道你可以使用C套接字库来实现C++,但我不确定.

是否有比其他人更频繁使用的C++套接字库?这不是一个主观问题,我实际上是在寻找Socket API /库对C++的作用.

我在套接字编程和C++方面相当新,所以请不要回答任何问题.

谢谢

c++ sockets network-programming

17
推荐指数
3
解决办法
3万
查看次数

了解套接字基础知识

我一直在阅读基本的网络编程,但我很难找到关于究竟和套接字是什么的直接解释,以及它与OSI或TCP/IP堆栈的关系.

  1. 有人可以向我解释插座是什么吗?它是程序员或API定义的数据结构,还是网卡上的硬件设备?

  2. 所提到的网络模型的哪些层面处理"原始"套接字?传输层?网络层?

  3. 就他们在它们之间传递的数据而言,是基于套接字文本还是二进制文件?

  4. 是否有基于套接字的网络编程的替代方案?或者所有联网应用程序都使用某种形式的套接字?

如果我能得到这么多,我应该非常清楚地理解我正在读的其他一切.谢谢你的帮助!

sockets network-programming

17
推荐指数
1
解决办法
7661
查看次数

getaddrinfo和IPv6

我试图了解getaddrinfo函数返回的内容:

#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netdb.h>

int main (int argc, char *argv[])
{


struct addrinfo *res = 0 ;

  getaddrinfo("localhost", NULL ,NULL,&res);
  printf("ai_flags -> %i\n", res->ai_flags) ;
  printf("ai_family -> %i\n", res->ai_family) ;
  printf("ai_socktype -> %i\n", res->ai_socktype) ;
  printf("ai_protocol -> %i\n", res->ai_protocol) ;
  printf("ai_addrlen -> %i\n", res->ai_addrlen) ;
  struct sockaddr_in* saddr = (struct sockaddr_in*)res->ai_addr;
  printf("ai_addr hostname ->  %s\n", inet_ntoa(saddr->sin_addr));

  freeaddrinfo(res);

  return 0 ;
}
Run Code Online (Sandbox Code Playgroud)

结果:

ai_flags -> 40
ai_family -> 2
ai_socktype -> 1
ai_protocol -> …
Run Code Online (Sandbox Code Playgroud)

c network-programming ipv4 ipv6 getaddrinfo

17
推荐指数
3
解决办法
2万
查看次数

如何在不轮询内核的情况下监视C程序中的NIC状态(向上/向下)?

现在我需要实时获取NIC的状态(向上或向下).这意味着当NIC在阻塞循环中上升或下降时,我必须捕获内核中断.

我的第一个愚蠢的方法是检查/ sys/class/net/eth0/operstate或使用ioctl在循环中每100ms获取一次ifflag.但是100ms太长了,应用程序无法重新路由流量,并且每隔100ms轮询内核也不是一个好主意.

一旦我注意到inotify函数可以在块模式下监视文件.但不幸的是,它无法监视/ sys/class/net/eth0/operstate文件,因为/ sys位于RAM而非磁盘中.

那么,除了编写内核模块以使用块模式捕获C程序中的NIC中断(向上/向下)之外,是否有任何方法?

linux networking network-programming linux-device-driver linux-kernel

17
推荐指数
2
解决办法
2万
查看次数

在Golang中检测不同类型网络错误的便携方式

我想确定网络级别发生了什么样的错误.我找到的唯一方法是使用正则表达式检查错误消息,但现在我发现此消息可以使用不同的语言(取决于操作系统配置),因此很难通过正则表达式进行检测.有没有更好的方法呢?

package main

import (
  "github.com/miekg/dns"
  "net"
  "regexp"
)

func main() {
  var c dns.Client
  m := new(dns.Msg)

  m.SetQuestion("3com.br.", dns.TypeSOA)
  _, _, err := c.Exchange(m, "ns1.3com.com.:53")
  checkErr(err)

  m.SetQuestion("example.com.", dns.TypeSOA)
  _, _, err = c.Exchange(m, "idontexist.br.:53")
  checkErr(err)

  m.SetQuestion("acasadocartaocuritiba.blog.br.", dns.TypeSOA)
  _, _, err = c.Exchange(m, "ns7.storedns22.in.:53")
  checkErr(err)
}

func checkErr(err error) {
  if err == nil {
    println("Ok")
  } else if netErr, ok := err.(net.Error); ok && netErr.Timeout() {
    println("Timeout")
  } else if match, _ := regexp.MatchString(".*lookup.*", err.Error()); match {
    println("Unknown host") …
Run Code Online (Sandbox Code Playgroud)

error-handling network-programming go

17
推荐指数
1
解决办法
6546
查看次数

套接字编程 - listen()和accept()之间有什么区别?

我一直在阅读本教程以了解套接字编程.似乎listen()accept()系统调用都做同样的事情,即阻塞并等待客户端连接到使用socket()系统调用创建的套接字.为什么你需要两个单独的步骤呢?为什么不只使用一个系统调用?

顺便说一句,我搜索了这个问题,发现了类似的问题,但没有一个答案令人满意.例如,其中一个人说accept()创建套接字是没有意义的,因为我知道套接字是由创建的socket().

c sockets network-programming tcp

17
推荐指数
3
解决办法
2万
查看次数