2010-10-28 229 views
9

我是一名優秀的程序員,但我沒有網絡經驗。客戶端 - 服務器網絡入門

基本上,我想進入客戶端 - 服務器網絡。例如,我想嘗試獲取服務器進程,以允許客戶端通過互聯網進行連接,並將ping發送給所有其他連接的客戶端。那麼也許我會嘗試開發一個簡單的聊天客戶端,或者一些簡單的多人遊戲,我會從那裏開始。

語言我心裏很清楚,可能是有用的:JAVA,C++,C

我該如何開始?我想先學習最佳實踐,那麼您可以推薦的良好學習資源(例如書籍,在線資料等)會很好。

編輯:我還應該看看某種虛擬機來模擬各種互相交互的機器嗎?

編輯2:我已經提出了50代表賞金。目前已經提出了一些很好的答案 - 儘管如此,我仍在尋找更詳細的答案,所以希望這會鼓勵這一點。例如,具有這種類型的東西,比較不同的學習方法的經驗的人的答案將是非常有用的。謝謝!我也可以獲得關於整個虛擬機的一些反饋嗎?

+1

只出於好奇。你如何設法「非常瞭解Java,C和C++」,但從未涉足網絡? – Cratylus 2010-10-28 19:36:10

+0

@ user384706:通過學習語言的語法,他們的大部分庫,並獲得大量的經驗。我指出,我擅長使用這些語言進行交流,我不需要初學者教程,旨在一起教授編程和網絡,或者面向初學者的程序員。就像「現在我們將學習while循環 - 然後,我們將繼續使用循環一次發送多個數據」:) – Cam 2010-10-28 19:40:53

+1

虛擬機並不是真的需要我的經驗...您可以模擬只需在單個操作系統下運行多個進程即可使用多臺機器 – 2010-10-30 21:57:18

回答

12

我更喜歡Java。我將解釋TCP:
基本概念是,您必須在機器上運行「服務器」。該服務器接受等待連接的客戶端。每個連接都通過一個端口(你知道,我希望...)。
始終使用端口1024以上的,因爲端口比1025低最的標準協議保留的時間(如HTTP(80),FTP(21),遠程登錄,...)

但是,創建Java中的一個服務器做這種方式:

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

「套接字」是你可能尋找,如果你想要做研究的話。
和你的客戶端連接到你有寫這個服務器:

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:當然,所有網絡代碼都必須嘗試處理IOException。

編輯:我忘了寫它爲什麼不總是最好的選擇。 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的字節。

6

Beej的網絡編程指南絕對是響亮的。在大學使用它。

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

它涵蓋了套接字API和記得它使用C++的代碼示例。

另外由Tannenbaum計算機網絡也是一個很好的閱讀。

+0

事實上,我有一些舊的客戶端和服務器代碼...它從我的Uni天,而不是有史以來最好的代碼,但也可能有幫助! – brumScouse 2010-10-28 19:18:50

+0

我簡要介紹了這本書,當我認識到內容時,我不認爲這是初學者學習基於IP的客戶端服務器網絡的最佳順序。 IMNSHO – 2010-10-28 19:27:17

+0

OP提到的其他方面的一些問題可能會很有用(例如一些簡單的客戶端和服務器程序),但我確實在我的答案中提到了作爲同伴的書。 – brumScouse 2010-10-28 19:32:58

1

不要從基礎開始,但那麼你應該看看什麼是真正使用(在Java中):

  1. 對於socket編程使用Apache Mina
  2. 現代客戶端服務器應用程序使用RESTJersey,RESTeasy(均爲JAX-RS complient)和Restlet(本領域的先驅者)。
3

在我的你應該學習如何使用sockets,讓我們說,在C,UNIX開始認爲(任何網上的教程將是合適的,或用「人」)。只有在那之後,您纔可以在語言/操作系統特定的庫中選擇Google,然後選擇您想要的或任何適合您需求的內容。

LE: 您可以隨時在同一臺機器上測試您的應用程序。

2

如果你一無所知TCP/IP,我會跟道格拉斯E. Comer的真棒書開始:TCP/IP卷1

你並不需要閱讀這一切,還有很多的有用的東西在那裏。

一旦你瞭解了這一點,就看看幾個開源網絡實現之一,比如boost asio。恕我直言,這是最容易啓動和運行的網絡庫。一旦這進一步激發了你的興趣,然後開始調查一些較低級別的套接字細節。順便說一句,brumScouse已經提到Beej的指導,這也是一個非常好的資源。

然後當你更進一步,你想要更多:谷歌C10K! ;)

+0

你會說Beej的指南屬於'低層套接字細節'的範圍嗎? – Cam 2010-10-28 23:45:55

+0

我們只是說,該指南是關於基本套接字API的;像asio或ACE或類似的庫簡單地包裝由套接字api公開的功能,併爲您提供良好的抽象。所以在這個意義上說,它稍微「低一級」,但同時它是非常有用的知識,讓你知道抽象如何工作。我首先提到抽象的原因是它隱藏了很多實現細節,您可能會迷失在... – Nim 2010-10-29 07:33:36

4

如果您使用的是C++,我強烈建議您使用Boost.Asio這是一個非常棒的異步網絡庫,它可以讓您比直接使用套接字更快地達到目標。

很顯然,從頭開始學習網絡資源是個好主意,但我認爲這樣做非常有益,因爲它有一個好的(易於使用的)庫來支持你,所以你也可以得到結果。

+0

對於C++解決方案而言,我強烈建議您查看Boost.Asio – 2010-11-01 01:00:50

6
  1. 瞭解有關網絡的基本概念。層,IP地址,端口,數據包[特別是UDP/TCP]

  2. 學習關於[1]的編程抽象,如套接字。

  3. 自己實施「服務器」和「客戶端」。

  4. 測試它。

  5. 在您的計算機上安裝Wireshark,並查找爲每種類型的活動發送的IP地址,數據包類型和端口號等。

  6. 通過使用Java/.Net/C++的網絡API構建知識。從頭開始構建一切可能是一個非常糟糕的主意。

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

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

C++:Unix網絡編程理查德·史蒂文斯

希望它能幫助。

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),但是如果您不習慣使用文件描述符,select,fork等,那麼這些都是事物你需要加快速度。

在我看來,最好的計劃之一是IRC客戶。它會給你所有你需要的基礎知識(讀/寫消息到服務器,併發連接,處理不同的服務器實現等),協議很容易解析,並且有很多服務器有連接。

2

您可能需要閱讀

Sockets programming in Java: A tutorial

上和javaworld。它解釋了基礎知識。最初不要試圖在低級網絡中做太多的事情。編寫一些簡單的客戶端/服務器來查看它是如何工作的。

2

這裏還沒有提到的東西。 Qt

Qt(C++框架)有一個非常好的「網絡」類,我用於TCP和UDP服務器/客戶端類型連接。有幾種不同的例子,涵蓋兩種:

阻斷連接(連接,這將使當前線程「等待」了一回)

非阻塞連接(連接掀起call_backs一旦數據可用)

Check it out你永遠不會回頭。他們非常有據可查!

1

Stevens'UNIX網絡編程擁有關於使用BSD套接字API(現在是標準套接字API)以及各種UNIX系統如何解釋這些API中的函數的所有信息。它包含了很多代碼,展示了正在討論的主題。它也很密集。

Beej的指南是如何使用套接字API的快速總結。它可能是一個更好的地方開始,只是把組裝服務器和客戶端的機制掛起來。要理解你爲什麼要按照這個順序對這些數據進行函數調用,以及函數調用的功能,你可以轉向Stevens。

如果您想挑選最佳實踐,請查看產品代碼:Mongrel 2如何處理聯網? lighttpd怎麼樣? Varnish?爲什麼他們按照他們的方式處理?

您也可以看看在你感興趣的一個平臺,網絡協議棧的實現。抓住內核源代碼,可能是一本書討論內核的設計,並在挖。

相關問題