天天看点

android网游开发之socket的简单设计和实现

对于普通应用的网络模块一般使用http文本协议,在android开发中使用http协议比较简单,sdk已经做了很好的封装了,具体使用方法可以参考我的这篇博文。而在游戏开发中,可以结合使用http和socket,当然了http协议底层也是基于tcp协议的。http协议是无连接、无状态的,每次连接只能处理一个请求,然后就断了,而且发一个请求需要附加额外信息(请求行、请求头),每次请求都需要重新建立连接;使用socket的好处是更高效和省流量,建立一次连接后,只要不手动或者出现异常断开,就可以一直互相发送数据,而且是直接以字节的形式发送,不需要额外的附加信息,缺点就是难度加大了,需要服务端和客户端很好的配合,保证发送和读取时数据的顺序一致。本文通过一个简单的demo介绍开发android网游时socket的使用方法,主要包括:android客户端和一个简单的使用java实现的server端,实现客户端和服务端互相发送数据的功能。

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上。下面分别是服务端的打印消息和客户端的显示截图。

android网游开发之socket的简单设计和实现
android网游开发之socket的简单设计和实现
android网游开发之socket的简单设计和实现

主要需要掌握基本数据类型和字符串跟字节数组的转换,然后按照指定的顺序发送。最重要的是要注意客户端和服务端从字节数组读取和往字节数组写入数据时的顺序要对应。

下面是源码链接:http://download.csdn.net/detail/zhoujianghai/4751981

继续阅读