小知识点:UDP协议和TCP协议的不同。UDP是把数据都打成数据包,数据包上自带通信的地址,但是数据包发出去之后UDP协议不能保证你能否收到。而TCP协议要求接收方收到数据后给个回应,当发送重要数据的时候就可以选择TCP协议。UDP发送数据的量是有限的,而TCP是没有限制的,当然这导致UDP很快,TCP相对慢点。根据不同的情况,有不同的选择。TCP能保证数据传输的成功性,UDP只传输,不保证传输的正确性。
一、通信的基本结构:客户端和服务器端
客户端这边是Socket类:客户端指定给某个服务器端上的某个端口发送消息。比如向56.152.16.5这台机器的19001号端口发送消息。
服务器端是ServiceSocket类:服务器端就在19001号这个端口上监听,一旦有消息来立刻捕捉还可以有所回应。
客户端通过OutputStream向服务器端发送数据,服务器端通过InputStream获取数据,即OutputStream(发)——>InputStream(收)。以字节流的方式获取数据。
如果服务器端想回发消息也是同样的道理。
二、实例讲解编写服务器端和客户端
1. 服务器端:这是个纯java的project,单独在一个工程。
01.import java.io.BufferedReader; 02.import java.io.IOException; 03.import java.io.InputStreamReader; 04.import java.net.ServerSocket; 05.import java.net.Socket; 06. 07.public class ServerSocketText { 08. 09. public static void main(String[] args) { 10. new ServerThread().start(); 11. 12. } 13. 14.} 15. 16.// 创建一个线程在后台监听 17.class ServerThread extends Thread { 18. private static int Port = 19001; 19. ServerSocket serversocket = null; 20. 21. public void run() { 22. 23. try { 24. // 创建一个serversocket对象,并让他在Port端口监听 25. serversocket = new ServerSocket(Port); 26. while (true) { 27. // 调用serversocket的accept()方法,接收客户端发送的请求 28. Socket socket = serversocket.accept(); 29. BufferedReader buffer = new BufferedReader( 30. new InputStreamReader(socket.getInputStream())); 31. // 读取数据 32. String msg = buffer.readLine(); 33. System.out.println("msg:" + msg); 34. } 35. 36. } catch (IOException e) { 37. e.printStackTrace(); 38. } finally { 39. try { 40. serversocket.close(); 41. } catch (IOException e) { 42. e.printStackTrace(); 43. } 44. } 45. } 46.}
2. 客户端:这是个android的客户端,用于发送消息。
01.import java.io.BufferedWriter; 02.import java.io.IOException; 03.import java.io.OutputStreamWriter; 04.import java.io.PrintWriter; 05.import java.net.InetAddress; 06.import java.net.NetworkInterface; 07.import java.net.Socket; 08.import java.net.SocketException; 09.import java.net.UnknownHostException; 10.import java.util.Enumeration; 11. 12.import android.app.Activity; 13.import android.os.Bundle; 14.import android.util.Log; 15.import android.view.View; 16.import android.view.View.OnClickListener; 17.import android.widget.Button; 18.import android.widget.EditText; 19. 20.public class Client extends Activity { 21. private static String IpAddress = "56.152.16.5"; 22. private static int Port = 10000; 23. private EditText edittext = null; 24. private Button send = null; 25. Socket socket = null; 26. 27. @Override 28. public void onCreate(Bundle savedInstanceState) { 29. super.onCreate(savedInstanceState); 30. setContentView(R.layout.main); 31. edittext = (EditText) findViewById(R.id.edittext); 32. send = (Button) findViewById(R.id.send); 33. send.setOnClickListener(new OnClickListener() { 34. 35. @Override 36. public void onClick(View v) { 37. sendMsg(); 38. 39. } 40. }); 41. } 42. 43. // 发送信息 44. public void sendMsg() { 45. 46. try { 47. // 创建socket对象,指定服务器端地址和端口号 48. socket = new Socket(IpAddress, Port); 49. // 获取 Client 端的输出流 50. PrintWriter out = new PrintWriter(new BufferedWriter( 51. new OutputStreamWriter(socket.getOutputStream())), true); 52. // 填充信息 53. out.println(edittext.getText()); 54. System.out.println("msg=" + edittext.getText()); 55. // 关闭 56. 57. } catch (UnknownHostException e1) { 58. e1.printStackTrace(); 59. } catch (IOException e1) { 60. e1.printStackTrace(); 61. } finally { 62. try { 63. socket.close(); 64. } catch (IOException e) { 65. e.printStackTrace(); 66. } 67. } 68. 69. } 70.}
3. 注意事项:
记得在AndroidManifest.xml中添加你的网络权限
<uses-permission android:name="android.permission.INTERNET"/>
activity布局就是一个edittext和已个button,所以没贴出代码。
运行时最好先android在服务器端,这样客户端发消息时才方便查看。
4. 疑问:
既然本例中socket建立的是TCP连接,那么客户端发完数据后socket关闭,服务器端socket也应该关闭,也就是不能再继续监听了,是这样吗?可能是,服务器的一个主线程在10000口监听,接受到一个客户端的请求则建立连接,并将该连接分配给一个线程,后主线程继续监听其他线程的请求。分配的线程接过连接大棒,与客户端交互。一旦客户端关闭连接,则该线程也关闭连接,结束。