`
19941021
  • 浏览: 5381 次
  • 性别: Icon_minigender_1
  • 来自: 长沙
最近访客 更多访客>>
社区版块
存档分类
最新评论
  • ayaome: ...
    java
  • 19941021:     明白了!谢谢了!
    java
  • ayaome: head属于LinkList类的属性你加个static关键字, ...
    java
  • 19941021:      这是因为在主函数中调用遍历链表的方法时要传入链表头的 ...
    java
  • ayaome: public static LinkNode head=nul ...
    java

Java SE通信开发小结(1)

阅读更多
[size=medium]
  
   通信项目做了好长时间,今天回过头,重新温习一下学过的知识,并总结一下知识。
   既然讲到通信,那么首先就要提到一个问题:
   什么是通信?
   我在未学习通信之前的理解:
        通信就是联网,不联网何来通信,联网之后进行数据传递就行了。
        对服务器,客户端都只是一个模糊的概念,只知大概,不知全貌。
        最可悲的是不知道数据是如何传递的。
   学习后对通信的理解:
        首先解释几个名词:
        服务器:在几台电脑之间建立连接之前,等待连接的机器。
        客户端:主动连接其他机器的机器。
        每台机器都有一个ip地址,和0~65535端口(0~1024已有其他用途,自己连接时最好不要用)
        网址与服务器地址的关系:服务器地址由9~10位数字组成,网址是一个域名,
                                两者是映射关系
        常用的几个与网络有关的dos命令
        1.ping netjava.cn   查看网络是否通畅
        2.telnet [服务器地址] [端口号]   连接服务器的指定端口
        3.netstat -an  查看和自己的机器通信的网络
        4.tracert [网址]  跟踪你的机器与连接目标地址间的路由器

        通信的途径就是:(核心就是协议)
        1.服务器和客户端建立连接
        2.获得两者的输入流,输出流
        3.制定协议
        4.根据服务器与客户端间制定的协议进行数据的读,写解析

        那么什么叫做协议呢?通俗的说就是两个人之间定义的一个口号,或一个约定
        你们按照自己的约定可以明白对方的意思,机器之间明确自己进行的操作。
       
         下面用代码简单实现以下发送聊天消息和文件:
         制定协议:
         消息:消息总长(int)+消息类型(byte)+消息内容(byte[])+目标客户账号(int)
        文件:文件数据总长(int)+数据类型(byte)+目标客户账号(int)+文件名(byte[256])
             +文件内容(byte[])

/**
 *界面等代码就省略了,只写下服务器和客户端的传输数据的功能实现
 *Client:客户端
 *Server:服务器
 */
package 通信;

import java.io.DataInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {

	// 启动主函数
	public static void main(String[] args) {
		Server se = new Server();
		se.setServer(8732);
	}

	public void setServer(int port) {
		try {
			// 建立绑定在指定端口上的服务器对象
			ServerSocket server = new ServerSocket(port);
			while (true) { // 让服务器进处循环等待状态
				Socket client = server.accept();				
				// 调用处理连接对象的方法去处理连接
				calChat(client);
			}
		} catch (Exception ef) {
			ef.printStackTrace();
		}
	}

	// 处理客户机进入的连接对象
	private void calChat(Socket client) {
		try {
			// 得到一个输出/输入流对象
			OutputStream out = client.getOutputStream();
			InputStream ins = client.getInputStream();
			// 将输入流包装为DataInputStream方便读取原始类型的流
			DataInputStream dins = new DataInputStream(ins);
			while (true) {
				// 开始读取数据:每一条消息
				// 1.读消息长度
				int totalLen = dins.readInt();
				// 2.读取消息类型标识
				byte flag = dins.readByte();
				// 3.读取目标客户账号
				int destNum = dins.readInt(); // 消息头解析完毕
				// 根据消息的类型,读取消息体部分
				if (flag == 1) {// 类型为1,是文本聊天消息,按其规则读取
					// 创建对应消息体部分字节的长度的数据
					byte[] data = new byte[totalLen - 4 - 1 - 4];
					// 从流中读取data.length个字节放入数组中
					dins.readFully(data);
					String msg = new String(data);// 转成字符串
				} else if (flag == 2) {// 文件数据包体解析
					System.out.println("发送文件给:" + destNum);
					byte[] data = new byte[256];
					dins.readFully(data);// 读取256个字节做文件名字
					// 解析出了文件名字,并去除末尾空格
					String fileName = new String(data).trim();
					// 余下的字节就是文件内容
					data = new byte[totalLen - 4 - 1 - 4 - 256];// 文件字节数据总长
					dins.readFully(data);// 读入文件的字节
					// 保存文件到当前目录下:
					FileOutputStream fous = new FileOutputStream(fileName);
					fous.write(data);
					fous.flush();  //将缓冲数据全部输出
					fous.close();  //关闭文件输出流
				} else {
					client.close();
				}
			}
		} catch (Exception ef) {
			ef.printStackTrace();
		}
	}

}

//客户端
package 通信;

import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Scanner;

public class Client {
	private DataOutputStream dous;// 输出流对象

	//发送字符串
	private void writeString(DataOutputStream out, String str,int length) {
		try {
			byte[] data = str.getBytes();  //将字符串转化为字符数组
			out.write(data);               //向服务器发送数据
			while(length>data.length){
				out.writeByte('\0');//补二进制0
				length--;
			}
		} catch (Exception ef) {
			ef.printStackTrace();
		}
	}

	//发送文本消息给目标账户
	private void sendTextMsg(String msg, int account) {
		try {
			byte[] sb = msg.getBytes();// 得到消息的字节数
			//消息总长=自身长度(int)+消息类型(byte)+账号(int)+消息内容(byte[])
			int totalLen = 4 + 1 + 4 + sb.length;
			dous.writeInt(totalLen); // 总长
			dous.writeByte(1); // 类型:1为文本消息
			dous.writeInt(account);// 写入目标用户号
			dous.write(sb);// 写入消息内容
			dous.flush();
		} catch (Exception ef) {
			ef.printStackTrace();
		}

	}

	//发送指定的文件给目标用户
	private void sendFile(String fileName, int destNum) {
		try {
			// 根据文件名创建文件对象
			File file = new File(fileName);
			// 根据文件对象,构造一个输入流
			InputStream ins = new FileInputStream(file);
			int fileDataLen = ins.available();// 文件数据总长
			int totalLen = 4 + 1 + 4 + 256 + fileDataLen; // 得到了要发送数据包的总长
			dous.writeInt(totalLen);
			dous.writeByte(2);// 类型是2,即文件数据包
			// 写入目标用户号
			dous.writeInt(destNum);
			// 文件名:得到文件的短名字
			String shortFileName = file.getName();
			// 写入文件名
			writeString(dous, shortFileName,256);
			byte[] fileData = new byte[fileDataLen];
			ins.read(fileData);// 读入文件数据
			dous.write(fileData);// 写出到服务器的流中
			dous.flush(); // 刷新流
		} catch (Exception ef) {
			ef.printStackTrace();
		}
	}

	//根据制定的服务器地址和端口连接服务器
	public void LinkServer(String ip, int port) {
		// 创建一个到服务器端的Socket对象
		try {
			Socket client = new Socket(ip, port);
			// 得到输入输出流对象
			InputStream ins = client.getInputStream();
			OutputStream ous = client.getOutputStream();
			// 将输出流包装为DataOutputStream对象
			dous = new DataOutputStream(ous);
			int num = 0;
			while (true) {
				System.out.println("登录服务器成功,请选择你要发的类型(1:聊天 2:文件:");

				// 让用户从命令行输入要发送的文件名字
				Scanner sc = new java.util.Scanner(System.in);
				int type = sc.nextInt();
				if (type == 1) {// 发文本
					sendTextMsg("我要发送问文本了" +num++, 8380);
				}
				if (type == 2) {// 发文件,注这个文件必须存在
					sendFile("d:\\wjh.txt", 8380);
				}
				num++;
			}
		} catch (Exception ef) {
			ef.printStackTrace();
		}
	}

	// 主函数
	public static void main(String[] args) {
		Client client = new Client();
		client.LinkServer("localhost", 8732);
	}
}



其实除了这种发送方式还有其他方式:
你把文件(MyFile)和消息(MyMessage)用类分装,将前面发送的东西设置为属性,在属性里面定义,set和get方法
发送时,先创建输入,输出流对象ins,dous
写入对象类型标识flag(byte)
然后用对象输入流封装ObjectInputStream input=new ObjectInputStream(ins);
调用input.ReadObject();
根据flag的值用相应类的对象接收
我以前也是用这种方法
最后调用该类的get方法输出,就ok了




该方法代码实现随后见通信(2)




[/size]
分享到:
评论

相关推荐

    基于Python的蓝桥杯竞赛平台的设计与实现

    【作品名称】:基于Python的蓝桥杯竞赛平台的设计与实现 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【项目介绍】:基于Python的蓝桥杯竞赛平台的设计与实现

    python实现基于深度学习TensorFlow框架的花朵识别项目源码.zip

    python实现基于深度学习TensorFlow框架的花朵识别项目源码.zip

    3-9.py

    3-9

    郊狼优化算法COA MATLAB源码, 应用案例为函数极值求解以及优化svm进行分类,代码注释详细,可结合自身需求进行应用

    郊狼优化算法COA MATLAB源码, 应用案例为函数极值求解以及优化svm进行分类,代码注释详细,可结合自身需求进行应用

    563563565+3859

    5635356

    客户培训课程–金字塔式写作方法.ppt

    客户培训课程–金字塔式写作方法.ppt

    工具与方法工作手册.ppt

    工具与方法工作手册.ppt

    Image_1715565894150.jpg

    Image_1715565894150.jpg

    setuptools-34.3.2-py2.py3-none-any.whl

    文件操作、数据分析和网络编程等。Python社区提供了大量的第三方库,如NumPy、Pandas和Requests,极大地丰富了Python的应用领域,从数据科学到Web开发。Python库的丰富性是Python成为最受欢迎的编程语言之一的关键原因之一。这些库不仅为初学者提供了快速入门的途径,而且为经验丰富的开发者提供了强大的工具,以高效率、高质量地完成复杂任务。例如,Matplotlib和Seaborn库在数据可视化领域内非常受欢迎,它们提供了广泛的工具和技术,可以创建高度定制化的图表和图形,帮助数据科学家和分析师在数据探索和结果展示中更有效地传达信息。

    C语言快速排序.doc

    快速排序 C语言快速排序.doc C语言快速排序.doc C语言快速排序.doc C语言快速排序.doc C语言快速排序.doc C语言快速排序.doc

    基于Python+MobileFaceNet的静默活体检测系统的设计与实现

    【作品名称】:基于Python+MobileFaceNet的静默活体检测系统的设计与实现 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【项目介绍】: 2、实验环境 Windows 10(64位) CPU:AMD Ryzen 7 5800H RAM:16G GPU:NVIDIA RTX3060 开发工具:IntelliJ IDEA以及PyCharm 相关配置及版本: Chrome 90.0.4430.212 SpringBoot 2.2.6 Java JDK8 MyBatis 2.1.1 Mysql 8.0.25 Python 3.8 pytorch 1.7.1 torchvision 0.8.2 numpy 1.18.5 tensorboard 2.4.1 pandas 1.2.3 cuda 11.0.2 cudnn 11.2 torch 1.8.1 torchvision 0.9.1 3、模型训练命令 python train.py 4、模型测试命令

    基于JavaScript的交通时空大数据分析挖掘系统源码+运行说明.zip

    基于JavaScript的交通时空大数据分析挖掘系统源码+运行说明 项目描述 项目核心是百度地图 AMap和 echarts,用百度地图提供的API搭建的地图,项目中用到的有热力图、散点图和连线图,图表类型是由echarts提供的图表进行展示,包括饼图、柱状图 安装依赖 javascript

    麦肯锡—xx集团战略咨询项目建议书.ppt

    麦肯锡—xx集团战略咨询项目建议书.ppt

    pytest-6.2.1-py3-none-any.whl

    文件操作、数据分析和网络编程等。Python社区提供了大量的第三方库,如NumPy、Pandas和Requests,极大地丰富了Python的应用领域,从数据科学到Web开发。Python库的丰富性是Python成为最受欢迎的编程语言之一的关键原因之一。这些库不仅为初学者提供了快速入门的途径,而且为经验丰富的开发者提供了强大的工具,以高效率、高质量地完成复杂任务。例如,Matplotlib和Seaborn库在数据可视化领域内非常受欢迎,它们提供了广泛的工具和技术,可以创建高度定制化的图表和图形,帮助数据科学家和分析师在数据探索和结果展示中更有效地传达信息。

    麦肯锡--战略咨询培训手册.ppt

    麦肯锡--战略咨询培训手册.ppt

    graspnet-pybullet

    graspnet-pybullet

    xx电器品牌战略和营销组织架构-SHA----d.ppt

    xx电器品牌战略和营销组织架构-SHA----d.ppt

    麦肯锡-战略规划模板.ppt

    麦肯锡-战略规划模板.ppt

    短视频拍摄-课程网盘链接提取码下载 .txt

    短视频拍摄-课程网盘链接提取码下载 .txt

    ruby源码资源包,冲冲冲!

    Ruby是一种为简单快捷面向对象编程而创建的脚本语言,由日本人松本行弘(まつもとゆきひろ,英译:Yukihiro Matsumoto,外号matz)开发,遵守GPL协议和Ruby License。Ruby的作者认为Ruby > (Smalltalk + Perl) / 2,表示Ruby是一个语法像Smalltalk一样完全面向对象、脚本执行、又有Perl强大的文字处理功能的编程语言。 Ruby以7月的诞生石ruby(红宝石)命名,是因为Perl的发音与6月的诞生石pearl(珍珠)相同。Ruby明显比其他类似的编程语言(如Perl或Python)年轻,又因为Ruby是日本人发明的,所以早期的非日文资料和程序都比较贫乏。

Global site tag (gtag.js) - Google Analytics