목차
'Unity3D' 카테고리의 다른 글
Tcp 라이브러리 - Unity3D 통신시 사용(멀티클라이언트 접속) (0) | 2017.01.20 |
---|---|
Unity Editor에서 코루틴 사용하기 (0) | 2017.01.11 |
목차
Packet.cs
using System;namespace Unity.Network{public enum PacketType{None, Connect, Reconnect, Disconnect, Chat,}[Serializable]public class Packet{public PacketType Type;}[Serializable]public class Connect : Packet{public string UserName;}[Serializable]public class ChatMessage : Packet{public string Message;}}
PacketBinder.cs
using System;
using System.Reflection;
using System.Runtime.Serialization;
namespace Unity.Network
{
sealed class PacketBinder : SerializationBinder
{
public override Type BindToType(string assemblyName, string typeName)
{
Type returntype = null;
assemblyName = Assembly.GetExecutingAssembly().FullName;
string sharedAssemblyName = "SharedAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null";
typeName = typeName.Replace(sharedAssemblyName, assemblyName);
returntype = Type.GetType(String.Format("{0}, {1}", typeName, assemblyName));
return returntype;
}
}
}
LocalClient.cs
using System;
using System.IO;
using System.Net.Sockets;
using System.Runtime.Serialization.Formatters.Binary;
namespace Unity.Network
{
public class LocalClient
{
private const string LocalIp = "127.0.0.1";
public const int PortNumber = 10001;
private const int BufferSize = 2048;
private NetworkStream _stream;
public NetworkStream Stream
{
get { return _stream; }
}
private readonly BinaryFormatter _formatter;
private TcpClient _client;
private byte[] _buffer;
public string UserName { get; set; }
public event Connected OnConnected;
public event Disconnected OnDisconnected;
public event ConnectError OnConnectError;
public event ReceiveObject OnReceiveObject;
/// <summary>
/// 클라이언트용 생성자
/// </summary>
public LocalClient() : this(null)
{
}
/// <summary>
/// 서버용 생성자
/// </summary>
/// <param name="client">이미 생성된 TcpClient</param>
public LocalClient(TcpClient client)
{
_client = client;
_formatter = new BinaryFormatter();
_formatter.Binder = new PacketBinder();
_buffer = new byte[BufferSize];
}
public void Start()
{
if (_client != null)
{
_stream = _client.GetStream();
//서버 -> 클라이언트
BeginRead();
}
else
{
//클라이언트 -> 서버
StartClient();
}
}
private void StartClient()
{
//클라이언트 -> 서버
_client = new TcpClient();
try
{
_client.BeginConnect(LocalIp, PortNumber, EndConnect, null);
}
catch (SocketException ex)
{
if (OnConnectError != null)
OnConnectError(ex);
}
}
private void EndConnect(IAsyncResult result)
{
try
{
_client.EndConnect(result);
_stream = _client.GetStream();
if (OnConnected != null)
OnConnected(this);
BeginRead();
}
catch (SocketException ex)
{
if (OnConnectError != null)
OnConnectError(ex);
}
}
private void BeginRead()
{
_stream.BeginRead(_buffer, 0, BufferSize, new AsyncCallback(ReadObject), null);
}
public void Close()
{
_stream.Close();
_client.Close();
}
private void ReadObject(IAsyncResult result)
{
int readSize = 0;
try
{
lock (_stream)
{
readSize = _stream.EndRead(result);
}
if (readSize < 1)
throw new Exception("Disconnect");
Packet packet = new Packet();
using (MemoryStream stream = new MemoryStream(_buffer))
{
packet = (Packet)_formatter.Deserialize(stream);
}
if (OnReceiveObject != null)
OnReceiveObject(this, packet);
lock (_stream)
{
BeginRead();
}
}
catch(Exception ex)
{
if (OnDisconnected != null)
OnDisconnected(this, ex);
}
}
public void SendPacket(Packet packet)
{
byte[] data = null;
try
{
using (MemoryStream stream = new MemoryStream())
{
_formatter.Serialize(stream, packet);
data = stream.ToArray();
}
if (data == null || data.Length < 1)
return;
_stream.Write(data, 0, data.Length);
_stream.Flush();
}
catch
{
}//try
}
}
public delegate void Connected(LocalClient client);
public delegate void Disconnected(LocalClient client, Exception ex);
public delegate void ConnectError(SocketException ex);
public delegate void ReceiveObject(LocalClient client, Packet packet);
}
NetMultiServer.cs
using System;
using System.Collections.Generic;
using System.Net.Sockets;
using System.Threading;
using Unity.Network;
namespace CsConnector
{
public class NetMultiServer
{
private readonly TcpListener _listener;
private readonly Dictionary<string, LocalClient> _clientTable;
private readonly Thread _listenerThread;
public NetMultiServer()
{
_clientTable = new Dictionary<string, LocalClient>();
_listener = new TcpListener(System.Net.IPAddress.Any, LocalClient.PortNumber);
_listenerThread = new Thread(new ThreadStart(DoListen));
}
public void Start()
{
_listenerThread.Start();
}
public void Close()
{
_listener.Stop();
}
private void DoListen()
{
try
{
_listener.Start();
do
{
TcpClient tcpClient = _listener.AcceptTcpClient();
LocalClient localClient = new LocalClient(tcpClient);
localClient.OnReceiveObject += ReceiveObject;
localClient.Start();
}
while (true);
}
catch (Exception)
{
}//try
}
private void ReceiveObject(LocalClient client, Packet packet)
{
if (packet == null)
return;
switch (packet.Type)
{
case PacketType.Connect: OnConnected(client, packet); break;
}
}
private void OnConnected(LocalClient client, Packet packet)
{
Connect connect = packet as Connect;
if (connect == null)
return;
client.UserName = connect.UserName;
_clientTable.Add(client.UserName, client);
}
private void SendPacket(LocalClient client, Packet packet)
{
client.SendPacket(packet);
}
}
}
NetClient.cs
using System;
using Unity.Network;
using UnityEngine;
public class NetClient
{
private const string UserName = "UnityClient";
private LocalClient _client;
public event Chat OnChat;
public NetClient()
{
}
public void Start()
{
_client = new LocalClient();
_client.OnConnected += Connected;
_client.Start();
}
public void Close()
{
_client.Close();
}
private void Connected(LocalClient client)
{
Connect connect = new Connect()
{
Type = PacketType.Connect,
UserName = UserName,
};
_client.UserName = UserName;
_client.SendPacket(connect);
}
private void ConnectError(Exception ex)
{
Debug.Log("접속 에러\n" + ex.ToString());
}
private void ReceiveObject(LocalClient client, Packet packet)
{
if (packet == null)
return;
switch (packet.Type)
{
case PacketType.Chat: OnChatMessage(client, packet); break;
}
}
private void OnChatMessage(LocalClient client, Packet packet)
{
ChatMessage message = packet as ChatMessage;
if (message == null)
return;
if (OnChat != null)
OnChat(message.Message);
}
private void SendPacket(LocalClient client, Packet packet)
{
client.SendPacket(packet);
}
public delegate void Chat(string message);
}
'Unity3D' 카테고리의 다른 글
Tcp 소켓 사용, Unity3D+Winform 메시지 주고받기 (0) | 2017.01.24 |
---|---|
Unity Editor에서 코루틴 사용하기 (0) | 2017.01.11 |
목차
프로젝트 소스 :
1. Visual Studio 2015 프로젝트
2. 테스트용 윈도우 서버, 클라이언트 모두 포함.
3. VS에서 실행시 서버, 클라이언트 동시동작
- 필요없는 경우 "한개의 시작 프로젝트"로 변경
4. "NamedPipeWrapper" 라이브러리
- Unity3D에서도 이 라이브러리를 사용하기 위해 .net Framework 3.5 기준으로 작성
- "ThreadPool.QueueUserWorkItem"으로 쓰레드 할당
'CSharp' 카테고리의 다른 글
C# FTP Class (0) | 2017.01.06 |
---|
목차
CoroutineRunner.cs
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
public static class CoroutineRunner
{
private static List _coroutineList = null;
private static List _bufferList = null;
public static IEnumerator Start(IEnumerator iterator)
{
if (_coroutineList == null)
_coroutineList = new List();
if (_bufferList == null)
_bufferList = new List();
if (_coroutineList.Count == 0)
EditorApplication.update += Update;
_bufferList.Add(iterator);
return iterator;
}
private static bool Find(IEnumerator iterator)
{
foreach (EditorCoroutine coroutine in _coroutineList)
{
if (coroutine.Find(iterator) == true)
return true;
}
return false;
}
private static void Update()
{
_coroutineList.RemoveAll
(
coroutine => { return coroutine.MoveNext() == false; }
);
if (_bufferList.Count > 0)
{
foreach (IEnumerator iterator in _bufferList)
{
if (Find(iterator) == false)
_coroutineList.Add(new EditorCoroutine(iterator));
}
_bufferList.Clear();
}
if (_coroutineList.Count == 0)
{
EditorApplication.update -= Update;
}
}
private class EditorCoroutine : IEnumerator
{
private Stack _stack;
public EditorCoroutine(IEnumerator iterator)
{
_stack = new Stack();
_stack.Push(iterator);
}
public bool MoveNext()
{
IEnumerator i = _stack.Peek();
if (i.MoveNext() == true)
{
object result = i.Current;
if (result != null && result is IEnumerator)
{
_stack.Push((IEnumerator)result);
}
return true;
}
else
{
if (_stack.Count > 1)
{
_stack.Pop();
return true;
}
}
return false;
}
public void Reset()
{
throw new System.NotSupportedException(
"This Operation Is Not Supported.");
}
public object Current
{
get { return _stack.Peek().Current; }
}
public bool Find(IEnumerator iterator)
{
return _stack.Contains(iterator);
}
}
}
'Unity3D' 카테고리의 다른 글
Tcp 소켓 사용, Unity3D+Winform 메시지 주고받기 (0) | 2017.01.24 |
---|---|
Tcp 라이브러리 - Unity3D 통신시 사용(멀티클라이언트 접속) (0) | 2017.01.20 |
목차
유니티에서 사용하는 FTP 접속방법이다. 만약 Winform이나 WPF 등에서 사용하려면 코루틴(IEnumerator) 부분을 쓰레드나 테스크, 이도저도 귀찮으면 그냥 void로 처리해서 사용하면 된다.
소스 :
간단한 사용 예시다.
Ftp ftp = new Ftp("ftp://서버주소", UserID, Password);
FtpConnection.Download(ftp, "c:\test.txt", "Builds/test.txt");
FtpConnection.cs
using System;
using System.Collections;
using System.IO;
using System.Net;
using UnityEngine;
public class FtpConnect
{
private static readonly int BufferSize = 2048;
public struct FileInfo
{
public bool IsDirectory;
public string Name;
public long Size;
}
public static IEnumerator Upload(Ftp ftp, string localFilePath, string remoteFilePath)
{
ftp.Connect(remoteFilePath, WebRequestMethods.Ftp.UploadFile);
FileStream localFileStream = new FileStream(localFilePath, FileMode.Open);
byte[] fileBuffer = new byte[BufferSize];
int fileSize = localFileStream.Read(fileBuffer, 0, BufferSize);
while (fileSize != 0)
{
ftp.Stream.Write(fileBuffer, 0, fileSize);
fileSize = localFileStream.Read(fileBuffer, 0, BufferSize);
}
localFileStream.Close();
ftp.Dispose();
yield return null;
}
public static IEnumerator Download(Ftp ftp, string localFilePath, string remoteFilePath)
{
ftp.Connect(remoteFilePath, WebRequestMethods.Ftp.DownloadFile);
FileStream localFileStream = new FileStream(localFilePath, FileMode.Create);
byte[] fileBuffer = new byte[BufferSize];
int fileSize = ftp.Stream.Read(fileBuffer, 0, BufferSize);
while (fileSize > 0)
{
localFileStream.Write(fileBuffer, 0, fileSize);
fileSize = ftp.Stream.Read(fileBuffer, 0, BufferSize);
}
localFileStream.Close();
ftp.Dispose();
yield return null;
}
public static void Delete(Ftp ftp, string remoteFilePath)
{
ftp.Connect(remoteFilePath, WebRequestMethods.Ftp.DeleteFile);
ftp.Dispose();
}
public static void Rename(Ftp ftp, string remoteFilePath, string newFileName)
{
ftp.Connect(remoteFilePath, WebRequestMethods.Ftp.Rename);
{
ftp.Request.RenameTo = newFileName;
ftp.Response = (FtpWebResponse)ftp.Request.GetResponse();
}
ftp.Dispose();
}
public static DateTime GetFileCreatedDateTime(Ftp ftp, string remoteFilePath, bool isKorean = true)
{
DateTime dateTime;
ftp.Connect(remoteFilePath, WebRequestMethods.Ftp.GetDateTimestamp);
{
dateTime = ftp.Response.LastModified;
}
ftp.Dispose();
dateTime = isKorean ? dateTime.AddHours(9) : dateTime;
return dateTime;
}
public static long GetFileSize(Ftp ftp, string remoteFilePath)
{
long size = 0;
ftp.Connect(remoteFilePath, WebRequestMethods.Ftp.GetFileSize);
{
size = (int)ftp.Response.ContentLength;
}
ftp.Dispose();
Debug.Log(size);
return size;
}
public static string[] GetListDirectory(Ftp ftp, string remoteDirectory)
{
string directoryRaw = "";
ftp.Connect(remoteDirectory, WebRequestMethods.Ftp.ListDirectory);
{
StreamReader reader = new StreamReader(ftp.Stream);
while (reader.Peek() != -1)
{
if (directoryRaw.Length > 0)
directoryRaw += "|";
directoryRaw += reader.ReadLine();
}
reader.Close();
}
ftp.Dispose();
return directoryRaw.Split("|".ToCharArray());
}
public static FileInfo[] GetListDirectoryDetails(Ftp ftp, string remoteDirectory)
{
string directoryRaw = "";
ftp.Connect(remoteDirectory, WebRequestMethods.Ftp.ListDirectoryDetails);
{
StreamReader reader = new StreamReader(ftp.Stream);
while (reader.Peek() != -1)
{
if (directoryRaw.Length > 0)
directoryRaw += "|";
directoryRaw += reader.ReadLine();
}
reader.Close();
}
ftp.Dispose();
string[] directories = directoryRaw.Split("|".ToCharArray());
FileInfo[] fileInfo = new FileInfo[directories.Length];
for(int i = 0; i < directories.Length; i++)
{
string[] tokens = directories[i].Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
fileInfo[i] = new FileInfo();
fileInfo[i].IsDirectory = tokens[0].StartsWith("d") ? true : false;
fileInfo[i].Size = long.Parse(tokens[4]);
fileInfo[i].Name = tokens[8];
}
return fileInfo;
}
public static bool IsExistDirectoryOrFile(Ftp ftp, string checkDirectoryName, string checkName)
{
string[] arr = GetListDirectory(ftp, checkDirectoryName);
foreach(string temp in arr)
{
if (temp == checkName)
return true;
}
return false;
}
public static void CreateDirectory(Ftp ftp, string newDirectoryName)
{
bool isCheck = IsExistDirectoryOrFile(ftp, newDirectoryName, newDirectoryName);
if (isCheck == true)
return;
ftp.Connect(newDirectoryName, WebRequestMethods.Ftp.MakeDirectory);
ftp.Dispose();
}
}
public class Ftp
{
private string _address;
public string Address
{
get { return _address; }
}
private string _id;
private string _pw;
private FtpWebRequest _request = null;
public FtpWebRequest Request
{
get { return _request; }
}
private FtpWebResponse _response = null;
public FtpWebResponse Response
{
get { return _response; }
set { _response = value; }
}
private Stream _stream = null;
public Stream Stream
{
get { return _stream; }
}
public Ftp(string address, string id, string pw)
{
_address = address;
if (_address.Substring(_address.Length - 1, 1) != "/")
_address += "/";
_id = id;
_pw = pw;
}
public void Connect(string filePath, string method)
{
try
{
string path = _address + filePath;
_request = (FtpWebRequest)FtpWebRequest.Create(path);
_request.Credentials = new NetworkCredential(_id, _pw);
_request.UseBinary = true;
_request.UsePassive = true;
_request.KeepAlive = true;
_request.Method = method;
switch(method)
{
case WebRequestMethods.Ftp.UploadFile:
_stream = _request.GetRequestStream();
break;
case WebRequestMethods.Ftp.DeleteFile:
case WebRequestMethods.Ftp.GetDateTimestamp:
case WebRequestMethods.Ftp.GetFileSize:
case WebRequestMethods.Ftp.MakeDirectory:
_response = (FtpWebResponse)_request.GetResponse();
break;
case WebRequestMethods.Ftp.DownloadFile:
case WebRequestMethods.Ftp.ListDirectoryDetails:
case WebRequestMethods.Ftp.ListDirectory:
_response = (FtpWebResponse)_request.GetResponse();
_stream = _response.GetResponseStream();
break;
}
}
catch (Exception ex)
{
throw ex;
}
}
public void Dispose()
{
if (_stream != null)
_stream.Close();
if (_response != null)
_response.Close();
_request = null;
}
}
'CSharp' 카테고리의 다른 글
C# NamedPipeline 사용예제 (0) | 2017.01.16 |
---|