Java Socket学习(二)——客户端服务端相互传输数据
来源:互联网 发布:幼儿网络安全教育教案 编辑:程序博客网 时间:2024/05/21 09:29
上一篇文章记录的是最基础的Socket和服务端连接,这篇文章记录的内容是:客户端与服务端相互传输数据的过程,其中客户端为安卓。如有不正确(有争议)的地方希望大家予以指正。
服务端
服务端如题使用Java编写,继续使用上一篇文章的部分代码。
服务端代码
package com.imudges.j2se.network;import com.google.gson.Gson;import java.io.*;import java.net.ServerSocket;import java.net.Socket;import java.util.HashMap;import java.util.Map;public class Server { private Socket socket; //声明一个ServerSocket对象 private ServerSocket serverSocket; //输入流 private BufferedReader bufferedReader; //输出流 private PrintWriter printWriter; //储存所有连接的socket private Map<String ,Socket> clientSocket = new HashMap<>(); private Gson gson = new Gson(); /** * 构造函数 * */ public Server() {} public static void main(String args[]){ Server server = new Server(); server.getServer(); } /** * 获取连接 * */ public void getServer(){ try { //绑定的端口为6666,此端口要与客户端请求的一致 serverSocket = new ServerSocket(6666); while(true){ System.err.println("等待客户端连接......"); //从队列中取出Socket或等待连接 socket = serverSocket.accept(); if (socket.isConnected()){ System.out.println("连接成功!"); } //开新的线程,为这个socket服务 new HandlerThread(socket); } } catch (IOException e) { e.printStackTrace(); } } /** * 实现一个Runnable接口,处理和client的一些事物 * */ private class HandlerThread implements Runnable{ private Socket socket; public HandlerThread(Socket socket) { this.socket = socket; new Thread(this).start(); } @Override public void run() { try { bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream())); //处理客户端发来的数据 String clientMsg = null; while ((clientMsg = bufferedReader.readLine())!=null){ System.out.println("客户端发来的消息:" + clientMsg); //向客户端回复信息 printWriter = new PrintWriter(socket.getOutputStream()); printWriter.println("ok"); printWriter.flush(); } } catch (IOException e) { e.printStackTrace(); } finally { if(socket != null){ try { socket.close(); } catch (IOException e) { socket = null; System.err.println("服务器finally异常,异常信息:" + e.getMessage()); } } } } }}
服务端启动之后的控制台如图:
有客户端连接后的控制台输出如图:
客户端发来消息后的控制台输出如图:
- 注:其中clientID为安卓的IMEI
客户端
客户端为Java,同时将Message封装为了一个Bean。
客户端代码
activity_main.xml
<?xml version="1.0" encoding="utf-8"?><LinearLayout 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" tools:context="com.demo.imudges.socketdemo.MainActivity" android:orientation="vertical"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="服务器说:"/> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/tv_server_msg" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="我给服务器说:"/> <EditText android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/et_cilent_send_msg" /> </LinearLayout> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="发送信息" android:gravity="center" android:id="@+id/btn_send_msg" /></LinearLayout>
Message.class
package com.demo.imudges.socketdemo;import android.content.Context;import android.widget.Toast;import java.io.*;import java.net.Socket;public class Client { private Socket socket; private PrintWriter printWriter;//输出 private BufferedReader bufferedReader; private static String URL = "183.175.12.168"; private static int port = 6666; public String msg = ""; private Context context; public Client(Context context) { this.context = context; //设置服务器IP,绑定端口 try { socket = new Socket(URL,port); System.out.println("连接完成!"); } catch (IOException e) { e.printStackTrace(); } } public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } public void sendMessage(){ try { //向服务器发送数据 //初始化输出流 用来向服务器传递数据 if(socket.isOutputShutdown()){ System.err.println("OutputStream 被关闭"); } printWriter = new PrintWriter(socket.getOutputStream(),true); printWriter.println(msg); //清空缓冲区的数据流 数据流向:内存->缓冲区->文件(或输出),如果不用.flush(),可能缓冲区内部还有数据残留,.flush()会将缓冲区内部的数据强制输出 printWriter.flush(); } catch (IOException e) { e.printStackTrace(); } } public interface Listener{ void update(String msg); } private Listener listener; public void setListener(Listener l){ this.listener = l; } public void getServerMsg(){ //接收服务器数据 //初始化输入流 用来获取服务器下发的数据 try { bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream())); String reply = null; while(!((reply = bufferedReader.readLine()) ==null)){ System.out.println("服务器发送的数据为:" + reply); listener.update(reply); } } catch (IOException e) { e.printStackTrace(); } }}
MainActivity.class
package com.demo.imudges.socketdemo;import Bean.Message;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.telephony.TelephonyManager;import android.text.TextUtils;import android.view.View;import android.widget.Button;import android.widget.EditText;import android.widget.TextView;import android.widget.Toast;import com.google.gson.Gson;public class MainActivity extends AppCompatActivity implements View.OnClickListener { private TextView tvServerMsg; private EditText etCLientSendMsg; private Button btnSendMsg; private TelephonyManager telephonyManager; private String IMEI = ""; private Client client; private Message message; private Gson gson = new Gson(); /** * 初始化控件 * */ private void initViews(){ etCLientSendMsg = (EditText) findViewById(R.id.et_cilent_send_msg); tvServerMsg = (TextView) findViewById(R.id.tv_server_msg); btnSendMsg = (Button) findViewById(R.id.btn_send_msg); btnSendMsg.setOnClickListener(this); telephonyManager = (TelephonyManager) this.getSystemService(this.TELEPHONY_SERVICE); //获取设备唯一ID IMEI = telephonyManager.getDeviceId(); } /** * 初始化事件 * */ private void initEvents(){ //判断是否获取到IMEI if(IMEI != null && !IMEI.equals("")){ new Thread(new Runnable() { @Override public void run() { client = new Client(MainActivity.this); client.setListener(new Client.Listener() { @Override public void update(final String msg) { if(msg!=null){ //子线程中更新界面 new Thread(new Runnable() { @Override public void run() { runOnUiThread(new Runnable() { @Override public void run() { //Message messageFromServer = gson.fromJson(msg,Message.class); tvServerMsg.setText(msg); } }); } }).start(); } } }); client.getServerMsg(); } }).start(); message = new Message(); message.setClientID(IMEI); } else { Toast.makeText(this,"获取IMEI失败",Toast.LENGTH_SHORT).show(); } } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initViews(); initEvents(); } @Override public void onClick(View view) { if(!TextUtils.isEmpty(etCLientSendMsg.getText())){ message.setMsg(etCLientSendMsg.getText().toString()); String msg = gson.toJson(message); client.setMsg(msg); new Thread(new Runnable() { @Override public void run() { client.sendMessage(); } }).start(); } else { } }}
Client.class
package com.demo.imudges.socketdemo;import android.content.Context;import android.widget.Toast;import java.io.*;import java.net.Socket;public class Client { private Socket socket; private PrintWriter printWriter;//输出 private BufferedReader bufferedReader; private static String URL = "183.175.12.168"; private static int port = 6666; public String msg = ""; private Context context; public Client(Context context) { this.context = context; //设置服务器IP,绑定端口 try { socket = new Socket(URL,port); System.out.println("连接完成!"); } catch (IOException e) { e.printStackTrace(); } } public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } public void sendMessage(){ try { //向服务器发送数据 //初始化输出流 用来向服务器传递数据 if(socket.isOutputShutdown()){ System.err.println("OutputStream 被关闭"); } printWriter = new PrintWriter(socket.getOutputStream(),true); printWriter.println(msg); //清空缓冲区的数据流 数据流向:内存->缓冲区->文件(或输出),如果不用.flush(),可能缓冲区内部还有数据残留,.flush()会将缓冲区内部的数据强制输出 printWriter.flush(); } catch (IOException e) { e.printStackTrace(); } } public interface Listener{ void update(String msg); } private Listener listener; public void setListener(Listener l){ this.listener = l; } public void getServerMsg(){ //接收服务器数据 //初始化输入流 用来获取服务器下发的数据 try { bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream())); String reply = null; while(!((reply = bufferedReader.readLine()) ==null)){ System.out.println("服务器发送的数据为:" + reply); listener.update(reply); } } catch (IOException e) { e.printStackTrace(); } }}
客户端发送消息后的截图:
贴上一张在网上找到的图片,个人觉得对于理解服务端和客户端Socket工作原理有所帮助。
- 最后总结一下我所踩的坑,希望大家引以为戒:
- 安卓端对于新开的线程,要用
.start()
方法启动,而不是.run()
。- 对于Socket接受和发送数据,无论是
socket.shutdownInput()
socket.shutdownOutput()
还是socket.close()
他们都会将Socket关闭,所以我使用printWriter.println()
发送数据,使用bufferReader.readLint()
接受数据,酱紫每次发送一行,每次读取一行,有明确的结束。同时不会使Scoket断开。(下面简单说说其他实现的方法)
2.1 使用Byte数组发送数据,每次发送的数据的第一位是数据长度,读取方只需要按照发送方给予的长度进行读取就可以,酱紫也不会使Socket断开。
2.2 发完就断开,断开重新连接。- 理清楚思路再写代码,不要让服务端和客户端同时等待输入或者是同时输出。酱紫会造成死循环?
socket.shutdownOutput()
socket.shutdownInput()
是单向关闭流。
阅读全文
0 0
- Java Socket学习(二)——客户端服务端相互传输数据
- 服务端和Android客户端利用Socket传输JSON数据
- Java Socket实现客户端服务端相互发送文本
- android客户端和java服务端之间用socket来传输图片(示例代码)
- android客户端和java服务端之间用socket来传输图片(示例代码)
- 用.Net打造一个移动客户端(Android/IOS)的服务端框架NHM(二)——“请求”“交互”与传输数据(服务器端)
- socket实现客户端与服务端通信(二)客户端
- 网络编程(15)—— 实现利用管道保存客户端数据的socket服务端
- Java Socket多线程服务端、客户端
- Java Socket多线程服务端、客户端
- 客户端通过Http传输数据到服务端
- android客户端和java服务端之间用socket来传输图片
- android客户端和java服务端之间用socket来传输图片
- android客户端和java服务端之间用socket来传输图片
- JAVA 网络编程 Socket 详细说明,实现客户端和服务端相互推送消息
- 足迹二:Android客户端与PC服务端之间的SOCKET通讯实现登陆功能(客户端 仅供学习)
- socket编程(二)通过服务端实现客户端之间通信
- java网络编程TCP传输—流操作—服务端反馈与客户端接收
- 关于使用ubuntu12.04安装ROS install阶段一直出现的404,403错误的解决办法
- 代码编辑器应该有语法高亮、自动补全,代码提示,格式化功能,代码跳转
- linux find 命令详解
- HTML meta标签总结,HTML5 head meta属性整理
- 全志R16平台的Android6系统下调通rtl8189es(分色排版)V1.1
- Java Socket学习(二)——客户端服务端相互传输数据
- Struts2拦截器配置
- Vim打开文件中文乱码
- 判断一个数是否为质数
- lnmp环境 laravel5.2 框架上线后报404
- idea14 如何创建传统的web项目 ,添加jar文件
- Windows上Python2和3如何兼容
- 数据结构-链表,队列,栈
- 蓝牙4.0BLE抓包(一)