客户端 - 服务器网络入门

时间:2010-10-28 19:15:08

标签: java c++ c network-programming

我是一名优秀的程序员,但我没有网络经验。

基本上,我想进入客户端 - 服务器网络。例如,我想尝试获取服务器进程,允许客户端通过Internet连接并将ping发送到所有其他连接的客户端。那么也许我会尝试开发一个简单的聊天客户端,或者一些简单的多人游戏,我会从那里开始。

我非常清楚可能有用的语言:Java,C ++,C。

我如何开始?我想预先学习最佳实践,所以你可以推荐的好学习资源(例如书籍,在线资料等)会很棒。

编辑:我是否还应该研究某种虚拟机来模拟彼此交互的各种机器?

编辑2:我已经提出了50个代表的奖金。到目前为止已经提出了一些很好的答案 - 我正在寻找更详细的答案,所以希望这会鼓励这样做。例如,具有这种比较不同学习方法的经验的人的答案将非常有帮助。谢谢!我也可以获得有关整个虚拟机的一些反馈吗?

13 个答案:

答案 0 :(得分:13)

我更喜欢Java。我将解释TCP:
基本概念是您必须在计算机上运行“服务器”。该服务器接受等待连接的客户端。每个连接都通过一个端口(你知道,我希望......) 始终使用1024以上的端口,因为低于1025的端口大部分时间是为标准协议保留的(如HTTP(80),FTP(21),Telnet,...)

但是,用Java创建服务器是这样做的:

ServerSocket server = new ServerSocket(8888); // 8888 is the port the server will listen on.

如果你想做研究,“Socket”就是你可能正在寻找的词 要将客户端连接到服务器,您必须写下:

Socket connectionToTheServer = new Socket("localhost", 8888); // First param: server-address, Second: the port

但现在,仍然没有联系。服务器必须接受等待的客户端(正如我在上面注意到的那样):

Socket connectionToTheClient = server.accept();

完成!您的连接已建立!通信就像File-IO一样。您唯一需要记住的是,您必须决定何时刷新缓冲区并真正通过套接字发送数据。
使用PrintStream进行文本编写非常方便:

OutputStream out = yourSocketHere.getOutputStream();
PrintStream ps = new PrintStream(out, true); // Second param: auto-flush on write = true
ps.println("Hello, Other side of the connection!");
// Now, you don't have to flush it, because of the auto-flush flag we turned on.

用于文本阅读的BufferedReader是好的(最佳*)选项:

InputStream in = yourSocketHere.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String line = br.readLine();
System.out.println(line); // Prints "Hello, Other side of the connection!", in this example (if this would be the other side of the connection.

希望您可以从这些信息的网络开始! PS:当然,所有网络代码都必须为IOExceptions尝试。

编辑:我忘了写为什么它并不总是最好的选择。 BufferedReader使用缓冲区并尽可能多地读取缓冲区。但有时你不希望BufferedReader在换行符之后窃取字节并将它们放入自己的缓冲区 简短的例子:

InputStream in = socket.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(in));
// The other side says hello:
String text = br.readLine();
// For whatever reason, you want to read one single byte from the stream,
// That single byte, just after the newline:
byte b = (byte) in.read();

但是BufferedReader已经在他的缓冲区中读取了那个字节。因此,调用in.read()将返回读取器缓冲区中最后一个字节后面的字节。

因此,在这种情况下,最好的解决方案是使用DataInputStream并以自己的方式管理它,以了解字符串的长度,并只读取该字节数并将其转换为字符串。或者:你使用

DataInputStream.readLine()

此方法不使用缓冲区并逐字节读取并检查换行符。所以这个方法不会从底层的InputStream中窃取字节。

答案 1 :(得分:6)

Beej的网络编程指南绝对响亮。在大学使用它。

http://beej.us/guide/bgnet/

它涵盖了套接字API,我记得它使用C ++代码示例。

Tannenbaum的计算机网络也是一本很好的读物。

答案 2 :(得分:6)

  1. 了解有关网络的基本概念。层,IP地址,端口,数据包[特别是UDP / TCP]

  2. 学习关于[1]的编程抽象,如套接字。

  3. 自己实施“服务器”和“客户”。

  4. 测试它。

  5. 在您的计算机上安装Wireshark,并查找为每种活动发送的IP地址,数据包类型,端口号等。

  6. 使用Java / .Net / C ++的Networking API构建知识。从头开始构建所有内容可能是一个非常糟糕的主意。

  7. Java:http://download.oracle.com/javase/tutorial/networking/index.html

    .Net:http://msdn.microsoft.com/en-us/library/4as0wz7t.aspx

    C ++:Richard Stevens的Unix网络编程

答案 3 :(得分:4)

如果您正在使用C ++,我强烈建议您使用Boost.Asio这是一个很棒的异步网络库,它可以让您比直接使用套接字更快地达到目标。

显然,从头开始学习网络资源是一个好主意,但我认为用一个好的(易于使用的)库来支持你是非常有益的,这样你就可以得到结果。

答案 4 :(得分:3)

在我看来,你应该首先学习如何使用sockets,比方说,在C,UNIX中(任何在线教程都适用,或使用“man”)。只有在那之后你才能谷歌搜索语言/操作系统特定的库,并选择你想要的任何东西或任何更适合你需要的东西。

LE: 您始终可以在同一台计算机上测试您的应用程序。

答案 5 :(得分:3)

我不能再推荐book by Richard Stevens

答案 6 :(得分:2)

如果您对TCP / IP一无所知,我将从Douglas E. Comer的一本很棒的书开始:TCP / IP第1卷。

你不需要阅读所有内容,那里有很多有用的东西。

一旦你了解了这一点,请查看几个开源网络实现之一,例如boost asio。恕我直言,这是最容易启动和运行的网络库。一旦这引起了你的兴趣,然后开始调查一些较低级别的套接字细节。顺便说一句,brumScouse已经提到了Beej的指南,这也是一个非常好的资源。

然后当你走得更远时,你想要更多:google C10K! ;)

答案 7 :(得分:2)

我来自一个主要是Linux网络编程的背景。我已经做了一些Windows套接字编程,从我看到的Windows套接字API非常类似于POSIX套接字API,并且在MSDN上有一些非常好的信息可以从POSIX移植到Windows套接字。

网络编程在概念上并不是很困难,有一些领域需要了解才能有效:首先,您需要对网络有基本的了解。您至少需要了解TCP和IPv4,因为这些可能是您最终使用的默认协议。在概念层面上了解一些关于DNS和以太网的内容可能也会有用,但一开始并不是严格要求的。一旦你有了一个基本的背景(阅读一些维基百科文章或网络的基本指南可能足以让你开始),你可以开始查看POSIX套接字API。一旦你掌握了网络基础知识,这些非常简单,并且有很多教程(Beej的网络编程指南被其他人列出,它非常好,而且手册页实际上也有一些非常有用的例子)。您可能遇到的最大绊脚石是知道网络字节顺序与主机字节顺序需要的内容,但根据经验,您写入套接字的任何内容都应首先放入网络字节顺序,以及任何内容你从套接字读取应立即转换为主机字节顺序。

很多人偶然发现,只是学习POSIX套接字API并不足以进行有效的网络编程。它会让你足够远,可以编写一个简单的echo客户端,但除此之外还有一些你需要熟悉的东西。最大的是处理非阻塞文件描述符,信号,使用select / epoll /等,并处理子进程工作流。从高层次来看,它在概念上非常简单(create-> bind-> listen-> select-> fork-> accept),但如果您不习惯使用文件描述符,请选择,fork等那些是你需要加快速度的东西。

在我看来,最好的程序之一是IRC客户端。它将为您提供所需的所有基础知识(读/写消息到服务器,并发连接,处理不同的服务器实现等),协议很容易解析,并且有很多服务器输出那里有连接。

答案 8 :(得分:2)

您可能需要阅读

Sockets programming in Java: A tutorial

在javaworld上。它解释了基础知识。最初不要试图在低级别网络中走得太远。编写一些简单的客户端/服务器来查看它是如何工作的。

答案 9 :(得分:2)

这里还没有提到的东西。 Qt的

Qt(c ++ framework)有一个非常好的“网络”类,我用它来进行TCP和UDP服务器/客户端类型的连接。有几个不同的例子涵盖了两者:

阻止连接(使当前线程“等待”返回的连接)

非阻塞连接(一旦数据可用就会引发call_backs的连接)

Check it out你永远不会回头。他们有很好的记录!

答案 10 :(得分:1)

从基础知识开始,然后你应该看看真正使用的是什么(在Java中):

  1. 对于套接字编程,请使用Apache Mina
  2. 现代客户端服务器应用使用RESTJerseyRESTeasy(均为JAX-RS complient)和Restlet(此字段中的先驱)。

答案 11 :(得分:1)

Stevens的 UNIX网络编程拥有您使用BSD套接字API(现在是标准套接字API)以及各种UNIX系统如何解释这些API中的功能所需的所有信息。它包含大量代码,用于演示正在讨论的主题。它也非常密集。

Beej的指南是如何使用套接字API的快速总结。它可能是一个更好的起点之一,只是掌握了将服务器和客户端放在一起的机制。要理解为什么要按顺序使用该数据进行这些函数调用,以及函数调用正在做什么,您可以转向Stevens。

如果您想了解最佳做法,请查看生产代码:Mongrel 2如何处理网络? lighttpd怎么样? Varnish?他们为什么这样做呢?

您还可以查看您感兴趣的平台的网络堆栈的实现。获取内核源代码,可能是一本讨论内核设计的书,然后深入研究。

答案 12 :(得分:0)

恕我直言,Java中的套接字编程比在C / C ++中容易得多。您可以从Java教程开始学习它:http://download.oracle.com/javase/tutorial/networking/sockets/

对于“基本”C / C ++套接字编程,您可以从"Beej's Guide to Network Programming"学习。我在大学时值得学习:)。然后,您可以了解下一个起点的Windows Socket API

要模拟环境,当然您可以使用VM:)