赞
踩
TCP协议: 提供IP环境下的数据 可靠传输 ,它提供的服务包括 数据流 传送、可靠性、有效流控、全双工操作和多路复用。通过面向连接、端到端和可靠的 数据包 发送。就如给悬崖上的两人通信时,他必须先把桥建好,确认桥是没问题的情况下,才把信件交过去,以后大家每次通信时,都确认下桥没什么问题,再通过这座桥来回通信了。
UDP协议: 不为IP提供可靠性、流控或差错恢复功能, 在正式通信前不必与对方先建立连接,不管对方状态就直接发送。这个就是飞鸽传书了~
虽然UDP可靠性不如TCP协议,但是 通信效率高于TCP。在网速极差的情况下优先考虑UDP协议,网速好的话TCP还是很方便使用的。
在Java中使用TCP可以通过java.net.Socket;这个类
<span style="font-family:Microsoft YaHei;font-size:18px;">建立连接</span>
- <span style="font-family:Microsoft YaHei;font-size:18px;">//实例化一个Socket对象
- socket = new Socket();
- //与对应的ip、端口进行连接,先要把桥建好
- socket.connect(new InetSocketAddress(ip, port), 3000);</span>
<span style="font-family:Microsoft YaHei;font-size:18px;">发送信息</span>
</pre><pre name="code" class="java"><span style="font-family:Microsoft YaHei;font-size:18px;">InputStream ois = socket.getInputStream(); DataInputStream dis = new DataInputStream(new BufferedInputStream(ois)); //读取服务器发过来的信息,如果没信息将会阻塞线程 msg = dis.readUTF();</span>
<span style="font-family:Microsoft YaHei;font-size:18px;">发送信息</span>
- <span style="font-family:Microsoft YaHei;font-size:18px;">//获得输出流
- DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(socket.getOutputStream()));
- //发送数据
- dos.writeUTF(msg);</span>
接下来上源码,为三个Thread的子类,分别对应上面三个
- <span style="font-family:Microsoft YaHei;font-size:18px;">public class SocketThread extends Thread{
-
- private Socket socket;
- private Client client;
- private String ip;
- private int port;
- private boolean isStart=false;
- private MessageListener mMessageListener;
-
- /**
- *
- * 使用TCP协议,连接访问
- * @param ip 目标机器的IP
- * @param port 端口
- * @param mMessageListener 收到服务器端数据时将回调该接口内的
- * public void Message(String msg)方法
- */
- public SocketThread(String ip, int port,
- MessageListener mMessageListener) {
- this.ip = ip;
- this.port = port;
- this.mMessageListener = mMessageListener;
- }
-
- public void run() {
- try {
- //实例化一个Socket对象
- socket = new Socket();
- //与对应的ip、端口进行连接,先要把桥建好
- socket.connect(new InetSocketAddress(ip, port), 3000);
- if (socket.isConnected()) {
- System.out.println("Connected..");
- client = new Client(socket,mMessageListener);
- //打开对应的输入/输出流监听
- client.start();
- isStart=true;
- }
- } catch (IOException e) {
- e.printStackTrace();
- isStart=false;
- }
- }
-
- // 直接通过client得到读线程
- public ClientInputThread getClientInputThread() {
- return client.getIn();
- }
-
- // 直接通过client得到写线程
- public ClientOutputThread getClientOutputThread() {
- return client.getOut();
- }
-
- //返回Socket状态
- public boolean isStart(){
- return isStart;
- }
-
- // 直接通过client停止读写消息
- public void setIsStart(boolean isStart) {
- this.isStart = isStart;
- client.getIn().setStart(isStart);
- client.getOut().setStart(isStart);
- }
-
- //发送消息
- public void sendMsg(String msg){
- client.getOut().sendMsg(msg);
- }
-
- public class Client {
-
- private ClientInputThread in;
- private ClientOutputThread out;
-
- public Client(Socket socket,MessageListener mMessageListener) {
- //用这个监听输入流线程来接收信息
- in = new ClientInputThread(socket);
- in.setMessageListener(mMessageListener);
- //以后就用这个监听输出流的线程来发送信息了
- out = new ClientOutputThread(socket);
- }
-
- public void start() {
- in.setStart(true);
- out.setStart(true);
- in.start();
- out.start();
- }
-
- // 得到读消息线程
- public ClientInputThread getIn() {
- return in;
- }
-
- // 得到写消息线程
- public ClientOutputThread getOut() {
- return out;
- }
- }
- }</span>

- <span style="font-family:Microsoft YaHei;font-size:18px;">public class ClientInputThread extends Thread {
- private Socket socket;
- private String msg;
- private boolean isStart = true;
- private InputStream ois;
- private DataInputStream dis;
- private MessageListener messageListener;// 消息监听接口对象
-
- public ClientInputThread(Socket socket) {
- this.socket = socket;
- try {
- ois = socket.getInputStream();
- dis = new DataInputStream(new BufferedInputStream(ois));
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
-
- /**
- * 提供给外部的消息监听方法
- *
- * @param messageListener
- * 消息监听接口对象
- */
- public void setMessageListener(MessageListener messageListener) {
- this.messageListener = messageListener;
- }
-
- public void setStart(boolean isStart) {
- this.isStart = isStart;
- }
-
- @Override
- public void run() {
- try {
- while (isStart) {
- //读取信息,如果没信息将会阻塞线程
- msg = dis.readUTF();
- // 每收到一条消息,就调用接口的方法Message(String msg)
- Log.v("收到消息", msg);
- messageListener.Message(msg);
- }
- ois.close();
- if (socket != null)
- socket.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
-
- BufferedReader reader=null;
- public String getInputStreamString() {
- /*
- * To convert the InputStream to String we use the
- * BufferedReader.readLine() method. We iterate until the BufferedReader
- * return null which means there's no more data to read. Each line will
- * appended to a StringBuilder and returned as String.
- */
- if (ois != null) {
- reader = new BufferedReader(new InputStreamReader(ois));
- }
- StringBuilder sb = new StringBuilder();
-
- String line = null;
- try {
- while ((line = reader.readLine()) != null) {
- sb.append(line + "\n");
- }
- } catch (IOException e) {
- e.printStackTrace();
- }
-
- return sb.toString();
- }
- }</span>

- <span style="font-family:Microsoft YaHei;font-size:18px;">public class ClientOutputThread extends Thread {
- private Socket socket;
- private DataOutputStream dos;
- private boolean isStart = true;
- private String msg;
-
- public ClientOutputThread(Socket socket) {
- this.socket = socket;
- try {
- dos = new DataOutputStream(new BufferedOutputStream(socket.getOutputStream()));
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
-
- public void setStart(boolean isStart) {
- this.isStart = isStart;
- }
-
- // 这里处理跟服务器是一样的
- public void sendMsg(String msg) {
- this.msg = msg;
- synchronized (this) {
- notifyAll();
- }
- }
-
- @Override
- public void run() {
- try {
- while (isStart) {
- if (msg != null) {
- dos.writeUTF(msg);
- dos.flush();
- msg=null;
- synchronized (this) {
- wait();// 发送完消息后,线程进入等待状态
- }
- }
- }
- dos.close();// 循环结束后,关闭输出流和socket
- if (socket != null)
- socket.close();
- } catch (InterruptedException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
-
- }</span>

<span style="font-family:Microsoft YaHei;font-size:18px;">//定义接收到消息时的,处理消息的接口 public interface MessageListener { public void Message(String msg); }</span>
主界面,感觉很丑,将就吧
<span style="font-family:Microsoft YaHei;font-size:18px;"><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="com.example.chatclient.MainActivity" > <ScrollView android:id="@+id/svMessage" android:layout_width="fill_parent" android:layout_height="100dp" > <TextView android:id="@+id/tvMessage" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="消息内容:\n" /> </ScrollView> <EditText android:id="@+id/etMessage" android:layout_width="100dp" android:layout_height="wrap_content" android:layout_below="@+id/svMessage" /> <TextView android:id="@+id/tvSend" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@+id/svMessage" android:layout_marginLeft="10dp" android:layout_toRightOf="@+id/etMessage" android:text="发送消息" android:textSize="25sp" /> " </RelativeLayout></span>MainActivity代码
- <span style="font-family:Microsoft YaHei;font-size:18px;">public class MainActivity extends Activity {
-
- EditText etMessage;
- TextView tvSend, tvMessage;
- SocketThread client;
- MyHandler myHandler;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- setup();
- }
-
- public void setup() {
- etMessage = (EditText) findViewById(R.id.etMessage);
- tvSend = (TextView) findViewById(R.id.tvSend);
- tvMessage = (TextView) findViewById(R.id.tvMessage);
- tvSend.setOnClickListener(onClick);
- myHandler = new MyHandler();
-
- //初始化
- client = new SocketThread("10.21.56.226", 8888,new MessageListener() {
-
- //收到消息后调用此方法
- @Override
- public void Message(String msg) {
- // TODO Auto-generated method stub
- // tvMessage.append(msg);
- Bundle bundle = new Bundle();
- bundle.putString("input", msg);
- Message isMessage = new Message();
- isMessage.setData(bundle);
- //使用handler转发
- myHandler.sendMessage(isMessage);
- }
- });
- //正式启动线程
- client.start();
-
- }
-
- OnClickListener onClick = new OnClickListener() {
- public void onClick(android.view.View v) {
- String message = etMessage.getText().toString();
- Log.v("发送消息", message);
- if (client.isStart()) {
- client.sendMsg(message);
- }
- };
- };
-
- private class MyHandler extends Handler {
- @Override
- public void handleMessage(Message msg) {
- // TODO Auto-generated method stub
- Log.v("处理收到的消息", " ");
- tvMessage.append(msg.getData().getString("input"));
- }
- }
- }</span>

服务器端的代码,主要是使用ServerSocket监听一个端口,来与客户端链接和收发信息
- <span style="font-family:Microsoft YaHei;font-size:18px;">public class ChatServer {
- boolean started = false;
- ServerSocket ss = null;
-
- List<Client> clients = new ArrayList<Client>();
-
- public static void main(String[] args) {
- new ChatServer().start();
- }
-
- public void start() {
- try {
- //ServerSocket监听8888端口
- ss = new ServerSocket(8888);
- started = true;
- } catch (BindException e) {
- System.out.println("start....");
- System.out.println("有问题");
- e.printStackTrace();
- System.exit(0);
- } catch (IOException e) {
- e.printStackTrace();
- }
-
- try {
-
- while (started) {
- Socket s = ss.accept();
- Client c = new Client(s);
- System.out.println("a client connected!");
- new Thread(c).start();
- clients.add(c);
- // dis.close();
- }
- } catch (IOException e) {
- e.printStackTrace();
- } finally {
- try {
- ss.close();
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- }
-
- class Client implements Runnable {
- private Socket s;
- private DataInputStream dis = null;
- private DataOutputStream dos = null;
- private boolean bConnected = false;
-
- public Client(Socket s) {
- this.s = s;
- try {
- dis = new DataInputStream(s.getInputStream());
- dos = new DataOutputStream(s.getOutputStream());
- bConnected = true;
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
-
- public void send(String str) {
- try {
- dos.writeUTF(str);
- } catch (IOException e) {
- clients.remove(this);
- System.out.println("关闭一个连接");
- // e.printStackTrace();
- }
- }
-
- public void run() {
- try {
- while (bConnected) {
- String str = dis.readUTF();
- System.out.println(str);
- for (int i = 0; i < clients.size(); i++) {
- Client c = clients.get(i);
- c.send(str);
- // System.out.println(" a string send !");
- }
- /*
- * for(Iterator<Client> it = clients.iterator();
- * it.hasNext(); ) { Client c = it.next(); c.send(str); }
- */
- /*
- * Iterator<Client> it = clients.iterator();
- * while(it.hasNext()) { Client c = it.next(); c.send(str);
- * }
- */
- }
- } catch (EOFException e) {
- System.out.println("Client closed!");
- } catch (IOException e) {
- e.printStackTrace();
- } finally {
- try {
- System.out.println("close All !");
- if (dis != null)
- dis.close();
- if (dos != null)
- dos.close();
- if (s != null) {
- s.close();
- // s = null;
- }
-
- } catch (IOException e1) {
- e1.printStackTrace();
- }
-
- }
- }
-
- }
- }</span>

接下来先运行服务器代码,再运行手机端就可以了,多台手机可以互相发送信息了。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。