干程序是一件枯燥重复的事,每当感到内心浮躁的时候,我就会找小说来看。我从小就喜爱看武侠小说,一直有着武侠梦。从金庸,古龙,梁羽生系列到凤歌(昆仑),孙晓(英雄志)以及萧鼎的(诛仙)让我领略着不一样的江湖。

如果你有好看的武侠系列小说,给我留言哦。题外话就扯这么多了,接着还是上技术。
看看今天实现的功能效果图:
可以这里使用多台手机进行通讯,我采用的服务器发送消息。
是不是只有发送消息,有些显得太单调了。好,在发送消息的基础上增加文件传输。后期会增加视频,音频的传输,增加表情包。那一起来看看图文消息的效果图,带领大家一起来实现通讯的简易聊天功能。
需要解决的难点:
如何判断socket接收的数据是字符串还是流?
如果你已是一名老司机,还请留言给出宝贵意见。带着这个疑问我们接着往下看。
Socket概述
Socket我们称之为"套接字",用于消息通知系统(如:激光推送),时事通讯系统(如:环信)等等。用于描述IP地址和端口,是一个通信链的句柄。网络上的两个程序通过一个双向的通讯连接实现数据的交换,这个双向链路的一端称为一个Socket,一个Socket由一个IP地址和一个端口号唯一确定(如:ServerSocket)。应用程序通常通过"套接字"向网络发出请求或者应答网络请求。Socket是TCP/IP协议的一个十分流行的编程界面,但是,Socket所支持的协议种类也不光TCP/IP一种,因此两者之间是没有必然联系的。在Java环境下,Socket编程主要是指基于TCP/IP协议的网络编程。
java.net包下有两个类:Socket和ServerSocket,基于TCP协议。
本文针对Socket和ServerSocket作主要讲解。
socket连接
建立Socket连接至少需要一对套接字,其中一个运行于客户端,称为ClientSocket ,另一个运行于服务器端,称为ServerSocket。
套接字之间的连接过程分为三个步骤:服务器监听,客户端请求,连接确认。步骤如下:
JDK Socket
在java.net包下有两个类:Socket和ServerSocket。ServerSocket用于服务器端,Socket是建立网络连接时使用的。在连接成功时,应用程序两端都会产生一个Socket实例,操作这个实例,完成所需的会话。对于一个网络连接来说,套接字是平等的,并没有差别,不因为在服务器端或在客户端而产生不同级别。不管是Socket还是ServerSocket它们的工作都是通过SocketImpl类及其子类完成的。接着了解下Socket和ServerSocket的构造方法。
Socket
Socket的构造方法:
Socket(InetAddress address,int port); //创建一个流套接字并将其连接到指定 IP 地址的指定端口号 Socket(String host,int port); //创建一个流套接字并将其连接到指定主机上的指定端口号 Socket(InetAddress address,int port, InetAddress localAddr,int localPort); //创建一个套接字并将其连接到指定远程地址上的指定远程端口 Socket(String host,int port, InetAddress localAddr,int localPort); //创建一个套接字并将其连接到指定远程主机上的指定远程端口 Socket(SocketImpl impl); //使用用户指定的 SocketImpl 创建一个未连接 Socket
参数含义:
注意:我们在选取端口号的时候需要特别注意,每一个端口提供一种特定的服务,只有给出正确的端口,才能获得相应的服务。0~1023的端口号为系统所保留,例如http服务的端口号为80,telnet服务的端口号为21,ftp服务的端口号为23。本文选取的端口号为30003
Socket的几个重要方法:
public InputStream getInputStream(); //方法获得网络连接输入,同时返回一个IutputStream对象实例 public OutputStream getOutputStream(); //方法连接的另一端将得到输入,同时返回一个OutputStream对象实例 public Socket accept(); //用于产生"阻塞",直到接受到一个连接,并且返回一个客户端的Socket对象实例。
对流的操作,操作完记得处理和关闭。以及对流异常的处理。
ServerSocket
ServerSocket的构造方法:
ServerSocket(int port); //创建绑定到特定端口的服务器套接字 ServerSocket(int port,int backlog); //利用指定的 backlog 创建服务器套接字并将其绑定到指定的本地端口号 ServerSocket(int port,int backlog, InetAddress bindAddr); //使用指定的端口、侦听 backlog 和要绑定到的本地 IP地址创建服务器
接着我们一起来看看案例。
发送和接收消息
首先来实现一个简单的案例,服务器端一直监听某个端口,等待客户端连接请求。客户端根据IP地址和端口号连接服务器端,接着客服端通过控制台向服务端发送消息,服务端接收到消息并且展示出来。下面来看看具体实现的步骤:
ClientSocket客服端:
try {
Socket socket = new Socket("173.1.1.121", 30004);
//获取控制台输入的内容
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
System.out.print("请输入发送的字符串:");
String str = bufferedReader.readLine();
//给服务端发送消息
PrintWriter printWriter = new PrintWriter(socket.getOutputStream());
printWriter.write(str + "\r\n");
printWriter.flush();
//关闭资源
bufferedReader.close();
printWriter.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
Socket两个参数分别是IP地址和端口号,可以通过以下代码获取IP地址:
InetAddress ia = null;
try {
ia = ia.getLocalHost();
String localname = ia.getHostName();
String localip = ia.getHostAddress();
System.out.println("本机名称是:" + localname);
System.out.println("本机的ip是 :" + localip);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
注意:关闭多余的网络适配,只保留当前的网络连接。关闭防火墙,安全软件。不然可能导致连接不上。
ServerSocket服务端:
try {
mServerSocket = new java.net.ServerSocket(30004);
Socket socket = mServerSocket.accept();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String content = null;
while ((content=bufferedReader.readLine() )!= null) {
System.out.println("接收到客服端发来的消息:" +content);
}
//关闭连接
bufferedReader.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
服务端和客服端的端口号必须保持一致。下面我们运行两个 java 程序看看效果:
可能有些童鞋还不知道,怎么在AndroidStudio下面运行java程序,请看下面截图:
传输文件
Socket只能通过流去读取消息,传输文件需要解决文章开始提出的问题, 如何判断socket接收的数据是字符串还是流?
定义协议
为了保证接收到的数据类型统一(数据是字符串还是流),需要定义协议。定义协议的方式有很多种:
我这里采用的自定义协议,原理跟前面两种类似。我传输的是JSON数据,根据字段标识传输的是字符串还是流,接收者根据标识去解析数据即可。
协议的实体类(Transmission):
//文件名称 public String fileName; //文件长度 public long fileLength; //传输类型 public int transmissionType; //传输内容 public String content; //传输的长度 public long transLength; //发送还是接受类型 1发送 2接收 public int itemType = 1; //0 文本 1 图片 public int showType;
根据字段transmissionType去标识传输(序列化)或接收(反序列化)的类型。传输的过程中始终都是以JSON的格式存在的。传输文件时需要把流转换成字符串(方式很多种我用的是Base64加密与解密)。
客户端(ClientThread)
客户端发送文件的代码如下:
/**
* 文件路径
*
* @param filePath
*/
private void sendFile(String filePath) {
FileInputStream fis = null;
File file = new File(filePath);
try {
mSendHandler.sendEmptyMessage(Constants.PROGRESS);
fis = new FileInputStream(file);
Transmission trans = new Transmission();
trans.transmissionType = Constants.TRANSFER_FILE;
trans.fileName = file.getName();
trans.fileLength = file.length();
trans.transLength = 0;
byte[] bytes = new byte[1024];
int length = 0;
while ((length = fis.read(bytes, 0, bytes.length)) != -1) {
trans.transLength += length;
trans.content = Base64Utils.encode(bytes);
mPrintWriter.write(mGson.toJson(trans) + "\r\n");
mPrintWriter.flush();
//更新进度
Message message = new Message();
message.what = Constants.PROGRESS;
message.obj = 100 * trans.transLength / trans.fileLength;
mSendHandler.sendMessage(message);
}
fis.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
if (fis != null) {
try {
fis.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
} catch (IOException e) {
e.printStackTrace();
mPrintWriter.close();
}
}
文章结尾处我会附上源码。
trans.content = Base64Utils.encode(bytes);
mPrintWriter.write(mGson.toJson(trans) + "\r\n");
mPrintWriter.flush();
把字节流转换成字符串传输Base64Utils.encode(bytes),接收方把字符串解析成字节流并写入文件。
注意:在Android程序中运行,记得添加网络文件读写的权限。
服务端(ServerThread)
服务端接收文件的代码如下:
long fileLength = trans.fileLength;
long transLength = trans.transLength;
if (mCreateFile) {
mCreateFile = false;
fos = new FileOutputStream(new File("d:/" + trans.fileName));
}
byte[] b = Base64Utils.decode(trans.content.getBytes());
fos.write(b, 0, b.length);
System.out.println("接收文件进度" + 100 * transLength / fileLength + "%...");
if (transLength == fileLength) {
mCreateFile = true;
fos.flush();
fos.close();
}
服务端接收到文件,并存储到了d盘。注意文件传输结束后关闭流。
源码地址:SocketDemo_jb51.rar
下载源码后,请先替换Constants类中HOST地址,然后运行MyServer的java程序,最后运行MainActivity的Android程序。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
# android
# socket实现聊天
# socket传输文件
# android简单聊天室
# 如何正确实现Android启动屏画面的方法(避免白屏)
# Android编程之简单启动画面实现方法
# Android简单实现启动画面的方法
# Android编程中调用Camera时预览画面有旋转问题的解决方法
# Android启动画面的实现方法
# Android开机画面的具体修改方法
# 详解Android——蓝牙技术 带你实现终端间数据传输
# Android实时获取摄像头画面传输至PC端思路详解
# 客户端
# 端口号
# 的是
# 服务端
# 客服
# 创建一个
# 发送消息
# 连接到
# 并将其
# 绑定
# 来看看
# 自定义
# 传输文件
# 本机
# 来实现
# 应用程序
# 文件传输
# 运行于
# 都是
# 如何判断
相关文章:
已有域名建站全流程解析:网站搭建步骤与建站工具选择
已有域名如何快速搭建专属网站?
如何通过服务器快速搭建网站?完整步骤解析
教学网站制作软件,学习*后期制作的网站有哪些?
制作宣传网站的软件,小红书可以宣传网站吗?
教学论文网站制作软件有哪些,写论文用什么软件
?
青岛网站设计制作公司,查询青岛招聘信息的网站有哪些?
安徽网站建设与外贸建站服务专业定制方案
如何在Ubuntu系统下快速搭建WordPress个人网站?
如何快速完成中国万网建站详细流程?
建站与域名管理如何高效结合?
如何解决ASP生成WAP建站中文乱码问题?
如何选择高效响应式自助建站源码系统?
建站之星如何配置系统实现高效建站?
七夕网站制作视频,七夕大促活动怎么报名?
制作表格网站有哪些,线上表格怎么弄?
无锡制作网站公司有哪些,无锡优八网络科技有限公司介绍?
网站制作培训多少钱一个月,网站优化seo培训课程有哪些?
南阳网站制作公司推荐,小学电子版试卷去哪里找资源好?
广州商城建站系统开发成本与周期如何控制?
一键制作网站软件下载安装,一键自动采集网页文档制作步骤?
网站好制作吗知乎,网站开发好学吗?有什么技巧?
创业网站制作流程,创业网站可靠吗?
北京的网站制作公司有哪些,哪个视频网站最好?
我的世界制作壁纸网站下载,手机怎么换我的世界壁纸?
如何在Golang中使用encoding/gob序列化对象_存储和传输数据
如何用AWS免费套餐快速搭建高效网站?
宝塔建站无法访问?如何排查配置与端口问题?
黑客入侵网站服务器的常见手法有哪些?
如何在建站之星绑定自定义域名?
桂林网站制作公司有哪些,桂林马拉松怎么报名?
微信推文制作网站有哪些,怎么做微信推文,急?
英语简历制作免费网站推荐,如何将简历翻译成英文?
网站制作说明怎么写,简述网页设计的流程并说明原因?
如何通过PHP快速构建高效问答网站功能?
Python路径拼接规范_跨平台处理说明【指导】
建站之星在线客服如何快速接入解答?
如何用虚拟主机快速搭建网站?详细步骤解析
大学网站设计制作软件有哪些,如何将网站制作成自己app?
免费制作统计图的网站有哪些,如何看待现如今年轻人买房难的情况?
深圳网站制作费用多少钱,读秀,深圳文献港这样的网站很多只提供网上试读,但有些人只要提供试读的文章就能全篇下载,这个是怎么弄的?
如何规划企业建站流程的关键步骤?
如何在阿里云部署织梦网站?
如何彻底删除建站之星生成的Banner?
教育培训网站制作流程,请问edu教育网站的域名怎么申请?
建站主机选哪种环境更利于SEO优化?
正规网站制作公司有哪些,目前国内哪家网页网站制作设计公司比较专业靠谱?口碑好?
公司网站设计制作厂家,怎么创建自己的一个网站?
安云自助建站系统如何快速提升SEO排名?
建站之星五站合一营销型网站搭建攻略,流量入口全覆盖优化指南
*请认真填写需求信息,我们会在24小时内与您取得联系。