1、想通过外网访问本地使用photon Server搭建的服务器怎么配置 win7,fast路由器 最好使用图片详解
首先要来排除电脑系统的问题,或源是硬件的问题。
然后就是检查IP设置的地方,DNS时候正确。
有的机子,之前设定的固定IP和DNS服务器和网关。
电信、长宽、铁通的DNS都会不同。
如果DNS不对,即使QQ等软件能正常上网,
也打不开网页。左键双击右下角的网络连接,
选择“常规”“属性”,双击“internet协议”
把“自动获得IP地址”和“自动获得DNS”都选中,
应用,就可以了。然后重启,连接上网
2、如果网络游戏运营商的服务器是光子服务器那游戏还坑钱吗?光子服务器能耗极小
玩儿游戏充值或者不充值是看自己意愿,再说了厂商研发的主要目的是赚钱。
3、photon可以做moba类游戏的服务器吗
服务器端源码:
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
/**
*
* 文件名:ServerReceive.java
* 实现功能:作为服务器接收客户端发送的文件
*
* 具体实现过程:
* 1、建立SocketServer,等待客户端的连接
* 2、当有客户端连接的时候,按照双方的约定,这时要读取一行数据
* 其中保存客户端要发送的文件名和文件大小信息
* 3、根据文件名在本地创建文件,并建立好流通信
* 4、循环接收数据包,将数据包写入文件
* 5、当接收数据的长度等于提前文件发过来的文件长度,即表示文件接收完毕,关闭文件
* 6、文件接收工作结束
public class ServerReceive {
public static void main(String[] args) {
/**与服务器建立连接的通信句柄*/
ServerSocket ss = null;
Socket s = null;
/**定义用于在接收后在本地创建的文件对象和文件输出流对象*/
File file = null;
FileOutputStream fos = null;
/**定义输入流,使用socket的inputStream对数据包进行输入*/
InputStream is = null;
/**定义byte数组来作为数据包的存储数据包*/
byte[] buffer = new byte[4096 * 5];
/**用来接收文件发送请求的字符串*/
String comm = null;
/**建立socekt通信,等待服务器进行连接*/
try {
ss = new ServerSocket(4004);
s = ss.accept();
} catch (IOException e) {
e.printStackTrace();
}
/**读取一行客户端发送过来的约定信息*/
try {
InputStreamReader isr = new InputStreamReader(s.getInputStream());
BufferedReader br = new BufferedReader(isr);
comm = br.readLine();
} catch (IOException e) {
System.out.println("服务器与客户端断开连接");
}
/**开始解析客户端发送过来的请求命令*/
int index = comm.indexOf("/#");
/**判断协议是否为发送文件的协议*/
String xieyi = comm.substring(0, index);
if(!xieyi.equals("111")){
System.out.println("服务器收到的协议码不正确");
return;
}
/**解析出文件的名字和大小*/
comm = comm.substring(index + 2);
index = comm.indexOf("/#");
String filename = comm.substring(0, index).trim();
String filesize = comm.substring(index + 2).trim();
/**创建空文件,用来进行接收文件*/
file = new File(filename);
if(!file.exists()){
try {
file.createNewFile();
} catch (IOException e) {
System.out.println("服务器端创建文件失败");
}
}else{
/**在此也可以询问是否覆盖*/
System.out.println("本路径已存在相同文件,进行覆盖");
}
/**【以上就是客户端代码中写到的服务器的准备部分】*/
/**
* 服务器接收文件的关键代码*/
try {
/**将文件包装到文件输出流对象中*/
fos = new FileOutputStream(file);
long file_size = Long.parseLong(filesize);
is = s.getInputStream();
/**size为每次接收数据包的长度*/
int size = 0;
/**count用来记录已接收到文件的长度*/
long count = 0;
/**使用while循环接收数据包*/
while(count < file_size){
/**从输入流中读取一个数据包*/
size = is.read(buffer);
/**将刚刚读取的数据包写到本地文件中去*/
fos.write(buffer, 0, size);
fos.flush();
/**将已接收到文件的长度+size*/
count += size;
System.out.println("服务器端接收到数据包,大小为" + size);
}
} catch (FileNotFoundException e) {
System.out.println("服务器写文件失败");
} catch (IOException e) {
System.out.println("服务器:客户端断开连接");
}finally{
/**
* 将打开的文件关闭
* 如有需要,也可以在此关闭socket连接
* */
try {
if(fos != null)
fos.close();
} catch (IOException e) {
e.printStackTrace();
}//catch (IOException e)
}//finally
}//public static void main(String[] args)
}//public class ServerReceive
客户端源码:
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.Socket;
/**
*
* 文件名:ClientSend.java
* 实现功能:作为客户端向服务器发送一个文件
*
* 具体实现过程:
* 1、建立与服务器端的连接,IP:127.0.0.1, port:4004
* 2、将文件的名字和大小通过自定义的文件传输协议,发送到服务器
* 3、循环读取本地文件,将文件打包发送到数据输出流中
* 4、关闭文件,结束传输
*
* */
public class ClientSend {
public static void main(String[] args) {
/**与服务器建立连接的通信句柄*/
Socket s = null;
/**定义文件对象,即为要发送的文件
* 如果使用绝对路径,不要忘记使用'/'和'\'的区别
* 具体区别,请读者自行查询
* */
File sendfile = new File("API.CHM");
/**定义文件输入流,用来打开、读取即将要发送的文件*/
FileInputStream fis = null;
/**定义byte数组来作为数据包的存储数据包*/
byte[] buffer = new byte[4096 * 5];
/**定义输出流,使用socket的outputStream对数据包进行输出*/
OutputStream os = null;
/**检查要发送的文件是否存在*/
if(!sendfile.exists()){
System.out.println("客户端:要发送的文件不存在");
return;
}
/**与服务器建立连接*/
try {
s = new Socket("127.0.0.1", 4004);
}catch (IOException e) {
System.out.println("未连接到服务器");
}
/**用文件对象初始化fis对象
* 以便于可以提取出文件的大小
* */
try {
fis = new FileInputStream(sendfile);
} catch (FileNotFoundException e1) {
e1.printStackTrace();
}
/**首先先向服务器发送关于文件的信息,以便于服务器进行接收的相关准备工作
* 具体的准备工作,请查看服务器代码。
*
* 发送的内容包括:发送文件协议码(此处为111)/#文件名(带后缀名)/#文件大小
* */
try {
PrintStream ps = new PrintStream(s.getOutputStream());
ps.println("111/#" + sendfile.getName() + "/#" + fis.available());
ps.flush();
} catch (IOException e) {
System.out.println("服务器连接中断");
}
/**
* 此处睡眠2s,等待服务器把相关的工作准备好
* 也是为了保证网络的延迟
* 读者可自行选择添加此代码
* */
try {
Thread.sleep(2000);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
/**之前的准备工作结束之后
* 下面就是文件传输的关键代码
* */
try {
/**获取socket的OutputStream,以便向其中写入数据包*/
os = s.getOutputStream();
/** size 用来记录每次读取文件的大小*/
int size = 0;
/**使用while循环读取文件,直到文件读取结束*/
while((size = fis.read(buffer)) != -1){
System.out.println("客户端发送数据包,大小为" + size);
/**向输出流中写入刚刚读到的数据包*/
os.write(buffer, 0, size);
/**刷新一下*/
os.flush();
}
} catch (FileNotFoundException e) {
System.out.println("客户端读取文件出错");
} catch (IOException e) {
System.out.println("客户端输出文件出错");
}finally{
/**
* 将打开的文件关闭
* 如有需要,也可以在此关闭socket连接
* */
try {
if(fis != null)
fis.close();
} catch (IOException e) {
System.out.println("客户端文件关闭出错");
}//catch (IOException e)
}//finally
}//public static void main(String[] args)
}//public class ClientSend
4、【Photon服务器】服务器端程序运行时报的错误Log,有大神知道都什么意思及解决办法吗?
PlayerHandler.cs:line 138,这里报错了,初步判断是数据传送的时候,解析出问题了
5、PhotonServer服务器连接mysql数据库报错,实在无力了,求大神!
本文将对NHibernate数据进行简单封装,方便在PhotonServer服务器中进行调用
[csharp] view plain copy
using NHibernate;
using NHibernate.Cfg;
using MyGameServer.Domain;
using NHibernate.Criterion;
using System.Collections.Generic;
namespace MyGameServer.Helper
{
public static class NHibernateHelper
{
private static ISessionFactory sessionFactory = null;
private static ISession session = null;
public static ISession GetSession
{
get
{
if (sessionFactory == null)
{
Configuration cfg = new Configuration();
//解析固定路径配置文件.cfg.xml
cfg.Configure();
//映射目标程序集 解析映射文件 Student.xml ......
cfg.AddAssembly(typeof(Student).Assembly);
//获取会话对象
sessionFactory = cfg.BuildSessionFactory();
}
session = sessionFactory.OpenSession();
return session;
}
private set { }
}
//添加行
public static void AddData<T>(T t)
{
using (ISession session = GetSession)
{
using (ITransaction transaction=session.BeginTransaction())
{
GetSession.Save(t);
transaction.Commit();
}
}
}
//添加列
public static void RemoveData<T>(T t)
{
using (ISession session = GetSession)
{
using (ITransaction transaction = session.BeginTransaction())
{
GetSession.Delete(t);
transaction.Commit();
}
}
}
//通过ID获取对象
public static T GetDataById<T>(int id)
{
using (ISession session = GetSession)
{
using (ITransaction transaction = session.BeginTransaction())
{
T t = session.Get<T>(id);
transaction.Commit();
return t;
}
}
}
/// <summary>
/// 通过名称获取对象
/// </summary>
/// <typeparam name="T">需要获取的对象</typeparam>
/// <param name="dataBaseName">在数据库中的列名称</param>
/// <param name="targetName">获取对象的目标名</param>
/// <returns></returns>
public static T GetDataByName<T>(string dataBaseName, string targetName)
{
using (ISession session = GetSession)
{
T t = session.CreateCriteria(typeof(T)).Add(Restrictions.Eq(dataBaseName, targetName)).UniqueResult<T>();
return t;
}
}
/// <summary>
/// 得到表内的全部对象
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public static ICollection<T> GetAllUsers<T>()
{
using (ISession session = GetSession)
{
IList<T> ts = session.CreateCriteria(typeof(T)).List<T>();
return ts;
}
}
//查询是否有符合id和姓名相同的对象
public static bool VerifyUser<T>(params object[] arg)
{
using (ISession session = GetSession)
{
T t = session
.CreateCriteria(typeof(T))
.Add(Restrictions.Eq(arg[0].ToString(), arg[1]))//类属性名 属性值
.Add(Restrictions.Eq(arg[2].ToString(), arg[3]))
.UniqueResult<T>();
if (t == null)
{
return false;
}
return true;
}
}
/// <summary>
/// 更新数据表
/// </summary>
/// <typeparam name="T">数据表映射的对象</typeparam>
/// <param name="t"></param>
public static void UpdateData<T>(T t)
{
using (ISession session = GetSession)
{
using (ITransaction transaction=session.BeginTransaction())
{
session.Update(t);
transaction.Commit();
}
}
}
}
}
在主函数调用
[csharp] view plain copy
using NHibernate;
using NHibernate.Cfg;
using LJL.Domain;
using LJL.Helper;
namespace LJL
{
class Program
{
static void Main(string[] args)
{
Student sd = new Student { mID = 6, mName = "小张", mScore = 10 };
NHibernateHelper.AddData(sd);
}
}
}
运行程序,一切正常,打开SQLyog,在student数据表中添加一行数据
接下来就是在PhotonServer中调用,来实现与MySQL数据库交互
按图下将类、配置文件集成到类库中(注意需要修改下类和配置文件中的程序集及命名空间)
接下来就是在Unity3d游戏客户端中与PhotonServer通信进而访问本地数据库
在Unity3d客户端上创建UI(这里简单拖入输入框和按钮)
如下图创建脚本
我们的游戏有很多中请求(比如登入、注册请求等等)
所以都继承自BaseRequest
[csharp] view plain copy
using ExitGames.Client.Photon;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public abstract class BaseRequest : MonoBehaviour
{
[HideInInspector]
//该请求的操作类型
public Collective.OperationMode operationMode = Collective.OperationMode.Default;
public virtual void Start() { }
public abstract void OnOperationRequest();
public abstract void OnOperationResponse(OperationResponse operationResponse);
}
这里博主简单的做了一下登录请求
[csharp] view plain copy
using ExitGames.Client.Photon;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class LoginRequest : BaseRequest
{
//用户名
private InputField mInputName;
//密码
private InputField mInputPassword;
public override void Start()
{
operationMode = Collective.OperationMode.LOGIN;
GameContext.GetInstance.AddRequest(this);
mInputName = GameObject.Find("IDInputField").GetComponent<InputField>();
mInputPassword = GameObject.Find("NameInputField").GetComponent<InputField>();
//登录按钮点击事件
GameObject.Find("LoginButton").GetComponent<Button>().onClick.AddListener(() => { OnOperationRequest(); });
}
public override void OnOperationRequest()
{
GameContext.GetInstance.peer.OpCustom(
(byte)this.operationMode,
new Dictionary<byte, object> { { (byte)Collective.ParameterMode.NAME, mInputName.text }, { (byte)Collective.ParameterMode.PASSWORD, mInputPassword.text } },
true
);
}
public override void OnOperationResponse(OperationResponse operationResponse)
{
Collective.OperationResult resultCode = (Collective.OperationResult)operationResponse.ReturnCode;
if (resultCode == Collective.OperationResult.SUCCESS)
{
//登录成功
Debug.Log("用户登录成功");
}
else if(resultCode == Collective.OperationResult.FAIL)
{
//登录失败
Debug.Log("登录失败");
}
}
}
最后附上上篇博文GameContext脚本,在这里有些地方发生了更新
[csharp] view plain copy
using System.Linq;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using ExitGames.Client.Photon;
public class GameContext : MonoBehaviour,IPhotonPeerListener
{
/// <summary>
/// 存储操作类型与请求
/// </summary>
public Dictionary<Collective.OperationMode, BaseRequest> requestDic = new Dictionary<Collective.OperationMode, BaseRequest>();
public PhotonPeer peer;
private static GameContext _instance;
public static GameContext GetInstance
{
get
{
if (_instance == null)
{
_instance = GameObject.Find("GameContext").GetComponent<GameContext>();
}
return _instance;
}
}
public void DebugReturn(DebugLevel level, string message)
{
}
//接收服务器发来的事件
public void OnEvent(EventData eventData)
{
switch (eventData.Code)
{
case 0:
//获取事件数据
object value = eventData.Parameters.FirstOrDefault(q => q.Key == 1).Value;
Debug.Log(value.ToString());
break;
default:
break;
}
}
//接收响应数据(客户端发送了请求)
public void OnOperationResponse(OperationResponse operationResponse)
{
BaseRequest request = requestDic.FirstOrDefault(q => q.Key == (Collective.OperationMode)operationResponse.OperationCode).Value;
if (request != null)
{
request.OnOperationResponse(operationResponse);
}
else
{
//获取响应数据失败
Debug.LogError("获取响应数据失败");
}
}
//连接状态发送改变
public void OnStatusChanged(StatusCode statusCode)
{
Debug.Log("数据连接状态发生的改变:" + statusCode);
}
private void Start()
{
//传输协议UDP 、 通过Listener接收服务器端的响应
peer = new PhotonPeer(this, ConnectionProtocol.Udp);
//连接本地服务器
peer.Connect("127.0.0.1:5055", "MYGameServer");
}
private void Update()
{
//和服务器实时保持数据连接
peer.Service();
}
private void OnDestroy()
{
if (peer != null && peer.PeerState == PeerStateValue.Connected)
{
//断开连接
peer.Disconnect();
}
}
public void AddRequest(BaseRequest request)
{
6、有人会用PhotonServer 作为unity 的服务器吗
photon 不是 网易那时候遗留下来的一个 服务端框架吗,那东西收费吧, 同步强连网还是自己写 soket 吧 比较稳妥,photon unity用的比较少吧
7、unity3d 网游服务器端如何选择
如果对楼主有帮助,给个采纳好不,谢谢啦
Photon和KBEngineunity3d是最适用Unity3d游戏开发的两个服务器引擎,但它们还是有区别的,只有清楚地了解区别在哪才能正确使用,下面简单描述下两者的共同点和不同点。
语言
对于大部分的程序员语言简直就是宗教信仰。
Photon使用C#开发,当然使用者也是用C#进行各类游戏功能开发。前后端同种语言,这对使用Unity3d游戏开发也有很大的好处。
KBEngine使用C++开发,逻辑开发是用python,也是很不错很快速的。
开源与收费情况
Photon是Exit Games公司的产品,不开源,有好多种收费模式,官网上可以看到。开发阶段可以用免费的license,后期可以看流量用户活跃度来选择付费模式。后续的支持,似乎是免费的,你可以选择邮件或是到论坛发帖求助,当然是E文。
KBEngine是国人开发,开源免费,但从官网上并没有看到商业使用的案例。有中文论坛,你可以在论坛上向开发者求助。
虽然两者的模式不同,但作为一个Unity3d游戏开发者,我们最希望的其实是把游戏引擎当作一个安全稳定的黑箱。
操作系统
之前说了Photon使用C#开发很自然的,配套的工具也是使用C#,比如最重要的PhotonControl。所以开发环境和生产环境最好都是windows。
虽然在跨平台上有mono,在服务器代码部分是系统无关的,但是不管你信不信,我是不信它的一套窗体工具也能运行在Linux下。反正,官网说法是,开发和生产环境都是用windows。
KBEngine建议开发环境选择Windows,生产环境选择linux。毕竟你总不希望开一组服务器打开9个Console窗体,一不小心把哪个点X了吧~
协议
Photon有自己的序列化反序列化方式,你也可以使用protobuf这类的来做应用层传输协议。
KBEngine在这方面表示不支持自定义协议,它帮你选择了有效的方法来处理,如果你习惯了他规定的方式,会喜欢上的。
看法
在功能上,我毫无疑问地更喜欢KBEngine,脚本化和自动持久化是极富魅力的功能。而Photon几乎没做这方面的功能,可能和老外的观念有关系。就目前我对两者功能的理解看来,Photon其实是个和SuperSocket差不多的东西,而SS是作为轻量级服务器框架存在的,Photon却是说自己是Unity3d游戏引擎,除去提供的MMO示例代码(未解读),没看到什么游戏引擎的魅力。
8、如何在android客户端连接电脑上搭建的Photon Server服务器端呢? 或者如何让另一
android客户端不来能直接与服务器数自据库连接,拿sqlserver来说,安装之后有几个G那么大,android程序是跑在手机上的,想让程序直接访问sqlserver,那手机需要非常大的内存。但是可以通过webservice这样一个桥梁来间接访问SQLServer。
即在服务器运行一个服务端程序,该服务端程序通过接收来自android客户端的指令,对数据库进行操作。客户端与服务端直接的数据传输主要通过http协议发送和接收json数据或者xml数据,服务端接收到客户端的json数据之后,进行json解析,再按一定的逻辑对数据库进行增、删、改、查。客户端的http请求可以通过 HttpClient类实现,在anddroid 4.0之后,客户端的网络请求已经不被允许在主线程中运行,所以题主还需注意另开启一个子线程进行网络请求。
9、有人会用PhotonServer 作为unity 的服务器吗
看英文是 证书获取 初始化 失败
可能是证源书有问题,其实我并不清楚
找到类似的文件
[email protected]
.license是证书的后缀,前面是你的注册邮箱找到一这个为结尾的文件就行
找到后,复制到你这个启动文件的目录。
友情提示:网上的教程已经过时,这个软件的一些构造函数已经变了,除非你能看懂官方文档,或者有人教你,不然,慎重选择
10、unity photon 能取代传统服务器吗
* 具体实现过程:
* 1、建立SocketServer,等待客户端的连接
* 2、当有客户端连接的时候,按照双方的约定,这时要读取一行数据
* 其中保存客户端要发送的文件名和文件大小信息
* 3、根据文件名在本地创建文件,并建立好流通信
* 4、循环接收数据包,将数据包写入文件
* 5、当接收数据的长度等于提前文件发过来的文件长度,即表示文件接收完毕,关闭文件
* 6、文件接收工作结束
public class ServerReceive {
public static void main(String[] args) {
/**与服务器建立连接的通信句柄*/
ServerSocket ss = null;
Socket s = null;
/**定义用于在接收后在本地创建的文件对象和文件输出流对象*/
File file = null;
FileOutputStream fos = null;
/**定义输入流,使用socket的inputStream对数据包进行输入*/
InputStream is = null;
/**定义byte数组来作为数据包的存储数据包*/
byte[] buffer = new byte[4096 * 5];
/**用来接收文件发送请求的字符串*/
String comm = null;
/**建立socekt通信,等待服务器进行连接*/
try {
ss = new ServerSocket(4004);
s = ss.accept();
} catch (IOException e) {
e.printStackTrace();
}
/**读取一行客户端发送过来的约定信息*/
try {
InputStreamReader isr = new InputStreamReader(s.getInputStream());
BufferedReader br = new BufferedReader(isr);
comm = br.readLine();
} catch (IOException e) {
System.out.println("服务器与客户端断开连接");
}
/**开始解析客户端发送过来的请求命令*/
int index = comm.indexOf("/#");
/**判断协议是否为发送文件的协议*/
String xieyi = comm.substring(0, index);
if(!xieyi.equals("111")){
System.out.println("服务器收到的协议码不正确");
return;
}
/**解析出文件的名字和大小*/
comm = comm.substring(index + 2);
index = comm.indexOf("/#");
String filename = comm.substring(0, index).trim();
String filesize = comm.substring(index + 2).trim();
/**创建空文件,用来进行接收文件*/
file = new File(filename);
if(!file.exists()){
try {
file.createNewFile();
} catch (IOException e) {
System.out.println("服务器端创建文件失败");
}
}else{
/**在此也可以询问是否覆盖*/
System.out.println("本路径已存在相同文件,进行覆盖");
}
/**【以上就是客户端代码中写到的服务器的准备部分】*/
/**
* 服务器接收文件的关键代码*/
try {
/**将文件包装到文件输出流对象中*/
fos = new FileOutputStream(file);
long file_size = Long.parseLong(filesize);
is = s.getInputStream();
/**size为每次接收数据包的长度*/
int size = 0;
/**count用来记录已接收到文件的长度*/
long count = 0;
/**使用while循环接收数据包*/
while(count < file_size){
/**从输入流中读取一个数据包*/
size = is.read(buffer);
/**将刚刚读取的数据包写到本地文件中去*/
fos.write(buffer, 0, size);
fos.flush();
/**将已接收到文件的长度+size*/
count += size;
System.out.println("服务器端接收到数据包,大小为" + size);
}
} catch (FileNotFoundException e) {
System.out.println("服务器写文件失败");
} catch (IOException e) {
System.out.println("服务器:客户端断开连接");
}finally{
/**
* 将打开的文件关闭
* 如有需要,也可以在此关闭socket连接
* */
try {
if(fos != null)
fos.close();
} catch (IOException e) {
e.printStackTrace();
}//catch (IOException e)
}//finally
}//public static void main(String[] args)
}//public class ServerReceive
客户端源码:
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.Socket;
/**
*
* 文件名:ClientSend.java
* 实现功能:作为客户端向服务器发送一个文件
*
* 具体实现过程:
* 1、建立与服务器端的连接,IP:127.0.0.1, port:4004
* 2、将文件的名字和大小通过自定义的文件传输协议,发送到服务器
* 3、循环读取本地文件,将文件打包发送到数据输出流中
* 4、关闭文件,结束传输
*
* */
public class ClientSend {
public static void main(String[] args) {
/**与服务器建立连接的通信句柄*/
Socket s = null;
/**定义文件对象,即为要发送的文件
* 如果使用绝对路径,不要忘记使用'/'和'\'的区别
* 具体区别,请读者自行查询
* */
File sendfile = new File("API.CHM");
/**定义文件输入流,用来打开、读取即将要发送的文件*/
FileInputStream fis = null;
/**定义byte数组来作为数据包的存储数据包*/
byte[] buffer = new byte[4096 * 5];
/**定义输出流,使用socket的outputStream对数据包进行输出*/
OutputStream os = null;
/**检查要发送的文件是否存在*/
if(!sendfile.exists()){
System.out.println("客户端:要发送的文件不存在");
return;
}
/**与服务器建立连接*/
try {
s = new Socket("127.0.0.1", 4004);
}catch (IOException e) {
System.out.println("未连接到服务器");
}
/**用文件对象初始化fis对象
* 以便于可以提取出文件的大小
* */
try {
fis = new FileInputStream(sendfile);
} catch (FileNotFoundException e1) {
e1.printStackTrace();
}
/**首先先向服务器发送关于文件的信息,以便于服务器进行接收的相关准备工作
* 具体的准备工作,请查看服务器代码。
*
* 发送的内容包括:发送文件协议码(此处为111)/#文件名(带后缀名)/#文件大小
* */
try {
PrintStream ps = new PrintStream(s.getOutputStream());
ps.println("111/#" + sendfile.getName() + "/#" + fis.available());
ps.flush();
} catch (IOException e) {
System.out.println("服务器连接中断");
}
/**
* 此处睡眠2s,等待服务器把相关的工作准备好
* 也是为了保证网络的延迟
* 读者可自行选择添加此代码
* */
try {
Thread.sleep(2000);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
/**之前的准备工作结束之后
* 下面就是文件传输的关键代码
* */
try {
/**获取socket的OutputStream,以便向其中写入数据包*/
os = s.getOutputStream();
/** size 用来记录每次读取文件的大小*/
int size = 0;
/**使用while循环读取文件,直到文件读取结束*/
while((size = fis.read(buffer)) != -1){
System.out.println("客户端发送数据包,大小为" + size);
/**向输出流中写入刚刚读到的数据包*/
os.write(buffer, 0, size);
/**刷新一下*/
os.flush();
}
} catch (FileNotFoundException e) {
System.out.println("客户端读取文件出错");
} catch (IOException e) {
System.out.println("客户端输出文件出错");
}finally{
/**
* 将打开的文件关闭
* 如有需要,也可以在此关闭socket连接
* */
try {
if(fis != null)
fis.close();
} catch (IOException e) {
System.out.println("客户端文件关闭出错");
}//catch (IOException e)
}//finally
}//public static void main(String[] args)
}//public class ClientSend