天天看點

網遊開發之socket的簡單設計

1.用戶端代碼實作

首先建立一個Android應用,名稱:AndroidSocketTest

然後分别建立4個檔案:BytesUtil.java、BytesReader.java、BytesWriter.java、TCPCommunication.java,下面分别介紹這幾個檔案的用處和源碼:

BytesUtil.java:包含了一些靜态工具方法:基本類型和位元組數組的互相轉換,字元串和位元組數組的互相轉換,位元組數組的指派和大小重置,對輸入流進行讀取儲存等。比較簡單,下面直接看源碼:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

<code>/**</code>

<code>author:alexzhou</code>

<code>email :[email protected]</code>

<code>date  :2012-11-7</code>

<code> </code><code>**/</code>

<code>public</code>

<code>final</code> <code>class</code> <code>BytesUtil {</code>

<code>    </code><code>/**</code>

<code>     </code><code>*整型轉換成位元組數組</code>

<code>     </code><code>* @param value 要轉換的整型值</code>

<code>     </code><code>* @return</code>

<code>     </code><code>*/</code>

<code>    </code><code>public</code>

<code>static</code> <code>byte</code><code>[] shortToBytes(</code><code>int</code>

<code>value) {</code>

<code>        </code><code>byte</code>

<code>[]write =</code><code>new</code>

<code>byte</code><code>[</code><code>2</code><code>];</code>

<code>        </code><code>write[</code><code>0</code><code>] = (</code><code>byte</code><code>)( (value &gt;&gt;&gt;</code><code>8</code><code>) &amp;</code><code>0xFF</code><code>);</code>

<code>        </code><code>write[</code><code>1</code><code>] = (</code><code>byte</code><code>)( (value &gt;&gt;&gt;</code><code>0</code><code>) &amp;</code><code>0xFF</code><code>);</code>

<code>        </code><code>return</code>

<code>write;</code>

<code>    </code><code>}</code>

<code>static</code> <code>byte</code><code>[] intToBytes(</code><code>int</code>

<code>byte</code><code>[</code><code>4</code><code>];</code>

<code>        </code><code>write[</code><code>0</code><code>] = (</code><code>byte</code><code>)( (value &gt;&gt;&gt;</code><code>24</code><code>) &amp;</code><code>0xFF</code><code>);</code>

<code>        </code><code>write[</code><code>1</code><code>] = (</code><code>byte</code><code>)( (value &gt;&gt;&gt;</code><code>16</code><code>) &amp;</code><code>0xFF</code><code>);</code>

<code>        </code><code>write[</code><code>2</code><code>] = (</code><code>byte</code><code>)( (value &gt;&gt;&gt;</code><code>8</code><code>) &amp;</code><code>0xFF</code><code>);</code>

<code>        </code><code>write[</code><code>3</code><code>] = (</code><code>byte</code><code>)( (value &gt;&gt;&gt;</code><code>0</code><code>) &amp;</code><code>0xFF</code><code>);</code>

<code>static</code> <code>byte</code><code>[] longToBytes(</code><code>long</code>

<code>byte</code><code>[</code><code>8</code><code>];</code>

<code>        </code><code>write[</code><code>0</code><code>] = (</code><code>byte</code><code>)( (value &gt;&gt;&gt;</code><code>56</code><code>) &amp;</code><code>0xFF</code><code>);</code>

<code>        </code><code>write[</code><code>1</code><code>] = (</code><code>byte</code><code>)( (value &gt;&gt;&gt;</code><code>48</code><code>) &amp;</code><code>0xFF</code><code>);</code>

<code>        </code><code>write[</code><code>2</code><code>] = (</code><code>byte</code><code>)( (value &gt;&gt;&gt;</code><code>40</code><code>) &amp;</code><code>0xFF</code><code>);</code>

<code>        </code><code>write[</code><code>3</code><code>] = (</code><code>byte</code><code>)( (value &gt;&gt;&gt;</code><code>32</code><code>) &amp;</code><code>0xFF</code><code>);</code>

<code>        </code><code>write[</code><code>4</code><code>] = (</code><code>byte</code><code>)( (value &gt;&gt;&gt;</code><code>24</code><code>) &amp;</code><code>0xFF</code><code>);</code>

<code>        </code><code>write[</code><code>5</code><code>] = (</code><code>byte</code><code>)( (value &gt;&gt;&gt;</code><code>16</code><code>) &amp;</code><code>0xFF</code><code>);</code>

<code>        </code><code>write[</code><code>6</code><code>] = (</code><code>byte</code><code>)( (value &gt;&gt;&gt;</code><code>8</code><code>) &amp;</code><code>0xFF</code><code>);</code>

<code>        </code><code>write[</code><code>7</code><code>] = (</code><code>byte</code><code>)( (value &gt;&gt;&gt;</code><code>0</code><code>) &amp;</code><code>0xFF</code><code>);</code>

<code>     </code><code>* 位元組數組轉換成整型</code>

<code>     </code><code>* @param value</code>

<code>static</code> <code>int</code> <code>bytesToInt(</code><code>byte</code>

<code>[]value) {</code>

<code>        </code><code>int</code>

<code>i1 = (value[</code><code>0</code><code>] &amp;</code><code>0xFF</code><code>) &lt;&lt;</code><code>24</code><code>;</code>

<code>i2 = (value[</code><code>1</code><code>] &amp;</code><code>0xFF</code><code>) &lt;&lt;</code><code>16</code><code>;</code>

<code>i3 = (value[</code><code>2</code><code>] &amp;</code><code>0xFF</code><code>) &lt;&lt;</code><code>8</code><code>;</code>

<code>i4 = (value[</code><code>3</code><code>] &amp;</code><code>0xFF</code><code>) &lt;&lt;</code><code>0</code><code>;</code>

<code>(i1 | i2 | i3 | i4);</code>

<code>static</code> <code>short</code> <code>bytesToShort(</code><code>byte</code><code>[] value) {</code>

<code>s1 = (value[</code><code>0</code><code>] &amp;</code><code>0xFF</code><code>) &lt;&lt;</code><code>8</code><code>;</code>

<code>s2 = (value[</code><code>1</code><code>] &amp;</code><code>0xFF</code><code>) &lt;&lt;</code><code>0</code><code>;</code>

<code>(</code><code>short</code><code>)(s1 | s2);</code>

<code>static</code> <code>long</code> <code>bytesToLong(</code><code>byte</code><code>[] value) {</code>

<code>        </code><code>long</code>

<code>L1 = (value[</code><code>0</code><code>] &amp;</code><code>0xFF</code><code>) &lt;&lt;</code><code>56</code><code>;</code>

<code>L2 = (value[</code><code>1</code><code>] &amp;</code><code>0xFF</code><code>) &lt;&lt;</code><code>48</code><code>;</code>

<code>L3 = (value[</code><code>2</code><code>] &amp;</code><code>0xFF</code><code>) &lt;&lt;</code><code>40</code><code>;</code>

<code>L4 = (value[</code><code>3</code><code>] &amp;</code><code>0xFF</code><code>) &lt;&lt;</code><code>32</code><code>;</code>

<code>L5 = (value[</code><code>4</code><code>] &amp;</code><code>0xFF</code><code>) &lt;&lt;</code><code>24</code><code>;</code>

<code>L6 = (value[</code><code>5</code><code>] &amp;</code><code>0xFF</code><code>) &lt;&lt;</code><code>16</code><code>;</code>

<code>L7 = (value[</code><code>6</code><code>] &amp;</code><code>0xFF</code><code>) &lt;&lt;</code><code>8</code><code>;</code>

<code>L8 = (value[</code><code>7</code><code>] &amp;</code><code>0xFF</code><code>) &lt;&lt;</code><code>0</code><code>;</code>

<code>(L1 | L2 | L3 | L4 | L5 | L6 | L7 | L8);</code>

<code>     </code><code>* 從指定位元組數組中拷貝部分資料</code>

<code>     </code><code>* @param origin</code>

<code>     </code><code>* @param from</code>

<code>     </code><code>* @param to</code>

<code>static</code> <code>byte</code><code>[] copyBytes(</code><code>byte</code><code>[] origin,</code><code>int</code>

<code>from,</code><code>int</code>

<code>to) {</code>

<code>len = to - from;</code>

<code>        </code><code>if</code><code>(len &lt;</code><code>0</code>

<code>|| origin.length - from &lt;=</code><code>0</code><code>) {</code>

<code>            </code><code>throw</code>

<code>new</code> <code>IllegalArgumentException(</code><code>"copyBytes-&gt;error arguments:to="</code><code>+to+</code><code>",from="</code><code>+from);</code>

<code>        </code><code>}</code>

<code>        </code><code>byte</code><code>[] ret =</code><code>new</code>

<code>byte</code><code>[len];</code>

<code>        </code><code>if</code><code>(len ==</code><code>0</code><code>)</code><code>return</code>

<code>ret;</code>

<code>        </code><code>System.arraycopy(origin, from, ret,</code><code>0</code><code>, Math.min(len, origin.length - from));</code>

<code>     </code><code>* 重置位元組數組的大小,然後把原内容複制到新的位元組數組中</code>

<code>     </code><code>* @param newSize</code>

<code>static</code> <code>byte</code><code>[] resizeBytes(</code><code>byte</code><code>[] origin,</code><code>int</code>

<code>newSize) {</code>

<code>        </code><code>if</code><code>(newSize &lt;</code><code>0</code><code>) {</code>

<code>new</code> <code>IllegalArgumentException(</code><code>"resizeBytes-&gt;newSize must &gt;= 0"</code><code>);</code>

<code>byte</code><code>[newSize];</code>

<code>        </code><code>if</code><code>(newSize ==</code><code>0</code><code>)</code><code>return</code>

<code>        </code><code>System.arraycopy(origin,</code><code>0</code><code>,ret,</code><code>0</code><code>,Math.min(origin.length, newSize));</code>

<code>     </code><code>* 讀取輸入流中位元組,并儲存到指定的位元組數組中</code>

<code>     </code><code>* @param is</code>

<code>     </code><code>* @param data</code>

<code>     </code><code>* @param off</code>

<code>     </code><code>* @param len</code>

<code>static</code> <code>void</code> <code>readData(InputStream is,</code><code>byte</code>

<code>data[],</code><code>int</code>

<code>off,</code><code>int</code>

<code>len) {</code>

<code>hasRead =</code><code>0</code><code>;</code>

<code>        </code><code>final</code>

<code>int</code> <code>BUFFER =</code><code>1024</code><code>;</code>

<code>        </code><code>while</code><code>(hasRead &lt; len) {</code>

<code>            </code><code>try</code>

<code>{</code>

<code>                </code><code>int</code>

<code>remain = len - hasRead;</code>

<code>count = is.read(data, off + hasRead, remain &gt; BUFFER ? BUFFER : remain);</code>

<code>                </code><code>if</code><code>(count &lt;</code><code>0</code><code>)</code><code>throw</code>

<code>new</code> <code>IOException(</code><code>"readData-&gt;read data error"</code><code>);</code>

<code>                </code><code>hasRead += count;</code>

<code>            </code><code>}</code><code>catch</code>

<code>(IOException e) {</code>

<code>                </code><code>e.printStackTrace();</code>

<code>            </code><code>}</code>

<code>}</code>

BytesReader.java:從服務端接收資料時使用,定義了一個位元組數組類型的成員變量,用來儲存從輸入流中讀取的資料。封裝了一些從該位元組數組中讀取相應資料類型的函數,源碼如下:

<code> </code><code>* 接受服務端資料時,讀取位元組并轉換到相應類型</code>

<code>final</code> <code>class</code> <code>BytesReader {</code>

<code>    </code><code>private</code>

<code>final</code> <code>byte</code> <code>[]data;</code>

<code>    </code><code>//位元組數組的大小</code>

<code>final</code> <code>int</code> <code>size;</code>

<code>    </code><code>//目前讀取的位置</code>

<code>int</code> <code>position;</code>

<code>BytesReader(</code><code>byte</code>

<code>[]data) {</code>

<code>        </code><code>this</code><code>.data = data;</code>

<code>        </code><code>this</code><code>.size = data.length;</code>

<code>        </code><code>this</code><code>.position =</code><code>0</code><code>;</code>

<code>byte</code><code>[] read(</code><code>int</code>

<code>        </code><code>if</code><code>(len &lt;</code><code>0</code><code>)</code><code>return</code>

<code>null</code><code>;</code>

<code>        </code><code>byte</code><code>[] value = BytesUtil.copyBytes(data, position, position + len);</code>

<code>        </code><code>this</code><code>.position += len;</code>

<code>value;</code>

<code>int</code> <code>getSize() {</code>

<code>size;</code>

<code>boolean</code> <code>isAvailable() {</code>

<code>size - position &gt;</code><code>0</code><code>;</code>

<code>short</code> <code>readShort() {</code>

<code>        </code><code>byte</code><code>[] value = read(</code><code>2</code><code>);</code>

<code>BytesUtil.bytesToShort(value);</code>

<code>int</code> <code>readInt() {</code>

<code>        </code><code>byte</code><code>[] value = read(</code><code>4</code><code>);</code>

<code>BytesUtil.bytesToInt(value);</code>

<code>long</code> <code>readLong() {</code>

<code>        </code><code>byte</code><code>[] value = read(</code><code>8</code><code>);</code>

<code>BytesUtil.bytesToLong(value);</code>

<code>byte</code> <code>readByte() {</code>

<code>value =</code><code>this</code><code>.isAvailable() ? (</code><code>0xFF</code>

<code>&amp; data[position++]) : -</code><code>1</code><code>;</code>

<code>(</code><code>byte</code><code>)value;</code>

<code>byte</code><code>[] readBytes() {</code>

<code>len = readShort();</code>

<code>        </code><code>//讀取大資料</code>

<code>        </code><code>if</code><code>(len &gt;=</code><code>0xFFFF</code><code>) {</code>

<code>            </code><code>len =</code><code>this</code><code>.readInt();</code>

<code>len ==</code><code>0</code>

<code>?</code><code>null</code>

<code>: read(len);</code>

<code>String readUTF() {</code>

<code>        </code><code>byte</code><code>[] bytes = readBytes();</code>

<code>        </code><code>if</code><code>(</code><code>null</code>

<code>!= bytes) {</code>

<code>                </code><code>return</code>

<code>new</code> <code>String(bytes,</code><code>"UTF-8"</code><code>);</code>

<code>(UnsupportedEncodingException e) {</code>

BytesWriter.java:向服務端發送資料時使用,跟BytesReader.java對應,也是把需要發送的資料儲存到位元組數組中,然後一次性發送給伺服器。源碼如下:

<code>date  :2012-11-9</code>

<code>final</code> <code>class</code> <code>BytesWriter {</code>

<code>byte</code><code>[] data;</code>

<code>int</code> <code>count;</code>

<code>BytesWriter() {</code>

<code>        </code><code>this</code><code>(</code><code>64</code><code>);</code>

<code>BytesWriter(</code><code>int</code>

<code>size) {</code>

<code>        </code><code>this</code><code>.data =</code><code>new</code>

<code>byte</code><code>[size];</code>

<code>byte</code><code>[] getBytes() {</code>

<code>this</code><code>.data.length == count ? data : count ==</code><code>0</code>

<code>: BytesUtil.resizeBytes(</code><code>this</code><code>.data, count);</code>

<code>void</code> <code>write(</code><code>byte</code><code>[] value) {</code>

<code>        </code><code>this</code><code>.write(value,</code><code>0</code><code>, value ==</code><code>null</code>

<code>?</code><code>0</code>

<code>: value.length);</code>

<code>void</code> <code>write(</code><code>byte</code><code>[] d,</code><code>int</code>

<code>offset,</code><code>int</code>

<code>        </code><code>if</code><code>(d ==</code><code>null</code>

<code>|| len ==</code><code>0</code><code>)</code><code>return</code><code>;</code>

<code>newCount = count + len;</code>

<code>        </code><code>if</code><code>(newCount &gt;</code><code>this</code><code>.data.length) {</code>

<code>            </code><code>int</code>

<code>newSize = Math.max(</code><code>this</code><code>.data.length &lt;&lt;</code><code>1</code><code>, newCount);</code>

<code>            </code><code>this</code><code>.data = BytesUtil.resizeBytes(</code><code>this</code><code>.data, newSize);</code>

<code>        </code><code>System.arraycopy(d, offset,</code><code>this</code><code>.data,</code><code>this</code><code>.count, len);</code>

<code>        </code><code>this</code><code>.count = newCount;</code>

<code>void</code> <code>writeInt(</code><code>int</code>

<code>        </code><code>this</code><code>.write(BytesUtil.intToBytes(value));</code>

<code>void</code> <code>writeShort(</code><code>int</code>

<code>        </code><code>this</code><code>.write(BytesUtil.shortToBytes(value));</code>

<code>void</code> <code>writeLong(</code><code>long</code>

<code>        </code><code>this</code><code>.write(BytesUtil.longToBytes(value));</code>

<code>void</code> <code>writeByte(</code><code>byte</code>

<code>newCount = count +</code><code>1</code><code>;</code>

<code>        </code><code>this</code><code>.data[count] = value;</code>

<code>void</code> <code>writeBytes(</code><code>byte</code><code>[] value) {</code>

<code>length = (value ==</code><code>null</code>

<code>        </code><code>//發送大資料時</code>

<code>        </code><code>if</code><code>(length &gt;=</code><code>0xFFFF</code><code>) {</code>

<code>            </code><code>this</code><code>.writeShort(</code><code>0xFFFF</code><code>);</code>

<code>            </code><code>this</code><code>.writeInt(length);</code>

<code>        </code><code>}</code><code>else</code>

<code>            </code><code>//告訴服務端發送的資料的大小</code>

<code>            </code><code>this</code><code>.writeShort(length);</code>

<code>        </code><code>this</code><code>.write(value);</code>

<code>void</code> <code>writeUTF(String value) {</code>

<code>        </code><code>if</code><code>(value ==</code><code>null</code>

<code>|| value.length() ==</code><code>0</code><code>) {</code>

<code>            </code><code>this</code><code>.writeShort(</code><code>0</code><code>);</code>

<code>        </code><code>byte</code><code>[] bytes =</code><code>null</code><code>;</code>

<code>        </code><code>try</code>

<code>            </code><code>bytes = value.getBytes(</code><code>"UTF-8"</code><code>);</code>

<code>        </code><code>}</code><code>catch</code>

<code>            </code><code>e.printStackTrace();</code>

<code>        </code><code>this</code><code>.writeBytes(bytes);</code>

TCPCommunication.java:上面的三個類都是輔助工具類,是給它使用的,它負責socket的建立和連接配接伺服器、讀取和發送資料,以及通過Handler發送消息給UI線程更新界面顯示資料。由于我們的目的是使用socket通信,是以去掉了很多代碼,這裡隻是簡單的建立一次連接配接,發送和接收完資料後就關閉連接配接了。源碼如下:

<code>class</code> <code>TCPCommunication</code><code>implements</code>

<code>Runnable {</code>

<code>Socket mSocket;</code>

<code>DataInputStream mDis;</code>

<code>DataOutputStream mDos;</code>

<code>Handler mHandler;</code>

<code>volatile</code> <code>boolean</code> <code>isRunning =</code><code>false</code><code>;</code>

<code>TCPCommunication(Handler handler) {</code>

<code>        </code><code>this</code><code>.mHandler = handler;</code>

<code>boolean</code> <code>isRunning() {</code>

<code>isRunning;</code>

<code>void</code> <code>startWork() {</code>

<code>        </code><code>Thread t =</code><code>new</code>

<code>Thread(</code><code>this</code><code>);</code>

<code>        </code><code>t.setPriority(Thread.MAX_PRIORITY);</code>

<code>        </code><code>t.start();</code>

<code>void</code> <code>stopWork() {</code>

<code>        </code><code>this</code><code>.isRunning =</code><code>false</code><code>;</code>

<code>    </code><code>@Override</code>

<code>void</code> <code>run() {</code>

<code>            </code><code>mSocket =</code><code>new</code>

<code>Socket(</code><code>"10.0.2.2"</code><code>,</code><code>8888</code><code>);</code>

<code>            </code><code>mDis =</code><code>new</code>

<code>DataInputStream(mSocket.getInputStream());</code>

<code>            </code><code>mDos =</code><code>new</code>

<code>DataOutputStream(mSocket.getOutputStream());</code>

<code>            </code><code>//開始發送資料到服務端</code>

<code>            </code><code>BytesWriter bw =</code><code>new</code>

<code>BytesWriter();</code>

<code>            </code><code>String username =</code><code>"alexzhou"</code><code>;</code>

<code>            </code><code>String password =</code><code>"123456"</code><code>;</code>

<code>flag1 =</code><code>12345</code><code>;</code>

<code>            </code><code>short</code>

<code>flag2 =</code><code>12</code><code>;</code>

<code>            </code><code>long</code>

<code>flag3 = 100000000L;</code>

<code>            </code><code>bw.writeUTF(username);</code>

<code>            </code><code>bw.writeUTF(password);</code>

<code>            </code><code>bw.writeInt(flag1);</code>

<code>            </code><code>bw.writeShort(flag2);</code>

<code>            </code><code>bw.writeLong(flag3);</code>

<code>            </code><code>byte</code><code>[] data = bw.getBytes();</code>

<code>            </code><code>BytesWriter out =</code><code>null</code><code>;</code>

<code>            </code><code>if</code><code>(data.length &gt;=</code><code>0xFFFF</code><code>) {</code>

<code>                </code><code>out =</code><code>new</code>

<code>BytesWriter(data.length +</code><code>6</code><code>);</code>

<code>                </code><code>out.writeShort(</code><code>0xFFFF</code><code>);</code>

<code>                </code><code>out.writeInt(data.length);</code>

<code>            </code><code>}</code><code>else</code><code>{</code>

<code>BytesWriter(data.length +</code><code>2</code><code>);</code>

<code>                </code><code>out.writeShort(data.length);</code>

<code>            </code><code>out.write(data);</code>

<code>            </code><code>mDos.write(out.getBytes());</code>

<code>            </code><code>//開始從服務端接收資料</code>

<code>len = mDis.readShort();</code>

<code>            </code><code>if</code><code>(len ==</code><code>0xFFFF</code><code>) {</code>

<code>                </code><code>len = mDis.readInt();</code>

<code>            </code><code>byte</code><code>[] inputData =</code><code>new</code>

<code>            </code><code>BytesUtil.readData(mDis, inputData,</code><code>0</code><code>, len);</code>

<code>            </code><code>BytesReader br =</code><code>new</code>

<code>BytesReader(inputData);</code>

<code>            </code><code>String user_id = br.readUTF();</code>

<code>            </code><code>String recv_username = br.readUTF();</code>

<code>            </code><code>String nickname = br.readUTF();</code>

<code>i = br.readInt();</code>

<code>s = br.readShort();</code>

<code>l = br.readLong();</code>

<code>            </code><code>String result =</code><code>"登入成功~您的資訊如下\n id:"</code><code>+user_id +</code><code>"\n使用者名:"</code>

<code>+ recv_username +</code><code>"\n昵稱:"</code>

<code>+ nickname +</code><code>"\n 序列号:"</code> <code>+ i +</code><code>"-"</code>

<code>+ s +</code><code>"-"</code>

<code>+ l;</code>

<code>            </code><code>Message msg = mHandler.obtainMessage();</code>

<code>            </code><code>msg.what =</code><code>0</code><code>;</code>

<code>            </code><code>msg.obj = result;</code>

<code>            </code><code>mHandler.sendMessage(msg);</code>

<code>            </code><code>mDis.close();</code>

<code>            </code><code>mDos.close();</code>

<code>            </code><code>mSocket.close();</code>

<code>(UnknownHostException e) {</code>

<code>    </code><code>};</code>

MainActivty.java的代碼比較簡單,源碼:

<code>class</code> <code>MainActivity</code><code>extends</code>

<code>Activity {</code>

<code>TextView mTextView;</code>

<code>Button mButton;</code>

<code>void</code> <code>onCreate(Bundle savedInstanceState) {</code>

<code>        </code><code>super</code><code>.onCreate(savedInstanceState);</code>

<code>        </code><code>setContentView(R.layout.activity_main);</code>

<code>        </code><code>mTextView = (TextView)</code><code>this</code><code>.findViewById(R.id.text);</code>

<code>        </code><code>mButton = (Button)</code><code>this</code><code>.findViewById(R.id.button_send);</code>

<code>        </code><code>mButton.setOnClickListener(</code><code>new</code>

<code>OnClickListener() {</code>

<code>            </code><code>@Override</code>

<code>            </code><code>public</code>

<code>void</code> <code>onClick(View v) {</code>

<code>                </code><code>new</code>

<code>TCPCommunication(mHandler).startWork();</code>

<code>        </code><code>});</code>

<code>Handler mHandler =</code><code>new</code>

<code>Handler() {</code>

<code>        </code><code>@Override</code>

<code>        </code><code>public</code>

<code>void</code> <code>handleMessage(Message msg) {</code>

<code>            </code><code>String result = (String)msg.obj;</code>

<code>            </code><code>mTextView.setText(result);</code>

<code>boolean</code> <code>onCreateOptionsMenu(Menu menu) {</code>

<code>        </code><code>getMenuInflater().inflate(R.menu.activity_main, menu);</code>

<code>true</code><code>;</code>

到此為止,Android用戶端的代碼已經全部完成了,記得給應用添加通路網絡的權限哦:在配置檔案中添加

<code>&lt;</code><code>uses-permission</code>

<code>android:name</code><code>=</code><code>"android.permission.INTERNET"</code>

<code>/&gt;</code>

2.服務端代碼實作

服務端的代碼比較簡單,當然了,一般在實際的開發中,服務端和用戶端不是同一個人寫的,這裡我就把用戶端裡的那幾個工具類拿來直接用了。

建立一個java項目,然後把BytesReader.java、BytesWriter.java、BytesUtil.java三個檔案拷貝到項目的包下,然後建立Server.java,功能比較簡單,監聽8888端口,然後等待用戶端連接配接,接收和發送資料。源碼如下:

<code>final</code> <code>class</code> <code>Server</code><code>implements</code>

<code>Runnable{</code>

<code>ServerSocket mServerSocket;</code>

<code>Socket mClient;</code>

<code>boolean</code> <code>isRunning =</code><code>false</code><code>;</code>

<code>void</code> <code>start() {</code>

<code>        </code><code>this</code><code>.isRunning =</code><code>true</code><code>;</code>

<code>void</code> <code>stop() {</code>

<code>static</code> <code>void</code> <code>main(String []args) {</code>

<code>        </code><code>new</code>

<code>Server().start();</code>

<code>            </code><code>mServerSocket =</code><code>new</code>

<code>ServerSocket(</code><code>8888</code><code>);</code>

<code>            </code><code>System.out.println(</code><code>"start server"</code><code>);</code>

<code>            </code><code>while</code><code>(isRunning) {</code>

<code>                </code><code>System.out.println(</code><code>"wait client connect!!"</code><code>);</code>

<code>                </code><code>mClient = mServerSocket.accept();</code>

<code>                </code><code>//接收用戶端發送的資料</code>

<code>                </code><code>mDis =</code><code>new</code>

<code>DataInputStream(mClient.getInputStream());</code>

<code>                </code><code>//資料的長度</code>

<code>                </code><code>if</code><code>(len ==</code><code>0xFFFF</code><code>) {</code>

<code>                    </code><code>len = mDis.readInt();</code>

<code>                </code><code>}</code>

<code>                </code><code>System.out.println(</code><code>"client data size:"</code> <code>+ len);</code>

<code>                </code><code>byte</code><code>[] inputData =</code><code>new</code>

<code>                </code><code>BytesUtil.readData(mDis, inputData,</code><code>0</code><code>, len);</code>

<code>                </code><code>BytesReader br =</code><code>new</code>

<code>                </code><code>String username = br.readUTF();</code>

<code>                </code><code>String password = br.readUTF();</code>

<code>                </code><code>short</code>

<code>                </code><code>long</code>

<code>                </code><code>System.out.println(</code><code>"username:"</code><code>+username+</code><code>";password="</code><code>+password+</code><code>"Long="</code><code>+l);</code>

<code>                </code><code>//向用戶端發送資料</code>

<code>                </code><code>mDos =</code><code>new</code>

<code>DataOutputStream(mClient.getOutputStream());</code>

<code>                </code><code>BytesWriter bw =</code><code>new</code>

<code>BytesWriter(</code><code>32</code><code>);</code>

<code>                </code><code>String user_id =</code><code>"123456"</code><code>;</code>

<code>                </code><code>String nickname =</code><code>"周江海"</code><code>;</code>

<code>                </code><code>bw.writeUTF(user_id);</code>

<code>                </code><code>bw.writeUTF(username);</code>

<code>                </code><code>bw.writeUTF(nickname);</code>

<code>                </code><code>bw.writeInt(i);</code>

<code>                </code><code>bw.writeShort(s);</code>

<code>                </code><code>bw.writeLong(l);</code>

<code>                </code><code>byte</code><code>[] data = bw.getBytes();</code>

<code>                </code><code>BytesWriter out =</code><code>null</code><code>;</code>

<code>                </code><code>if</code><code>(data.length &gt;=</code><code>0xFFFF</code><code>) {</code>

<code>                    </code><code>out =</code><code>new</code>

<code>                    </code><code>out.writeShort(</code><code>0xFFFF</code><code>);</code>

<code>                    </code><code>out.writeInt(data.length);</code>

<code>                </code><code>}</code><code>else</code>

<code>                    </code><code>out.writeShort(data.length);</code>

<code>                </code><code>out.write(data);</code>

<code>                </code><code>mDos.write(out.getBytes());</code>

<code>                </code><code>mDos.close();</code>

<code>                </code><code>mDis.close();</code>

<code>                </code><code>mClient.close();</code>

<code>        </code><code>}  </code>

現在驗證一下,先啟動Server,然後運作Android用戶端應用,螢幕中間會出現TextView和一個button,TextView的内容是HelloWorld,點選button就會發送登陸資訊給服務端,然後服務端傳回資料顯示到TextView上。下面分别是服務端的列印消息和用戶端的顯示截圖。

網遊開發之socket的簡單設計
網遊開發之socket的簡單設計
網遊開發之socket的簡單設計

主要需要掌握基本資料類型和字元串跟位元組數組的轉換,然後按照指定的順序發送。最重要的是要注意用戶端和服務端從位元組數組讀取和往位元組數組寫入資料時的順序要對應。

繼續閱讀