using System.Collections
using System.Collections.Generic
using UnityEngine
using System.Net.Sockets
using System
using UnityEngine.Networking
using System.Text
using Google.Protobuf
using Pb
using System.Net
using System.IO
namespace Net
{
public class SocketClient
{
#region Public Variables
public static SocketClient Instance { getprivate set}
[Header("Network")]
public string ipAdress = "127.0.0.1"
public int port = 8000
public float waitingMessagesFrequency = 1
public bool loggedIn { getprivate set}
public bool FullLog = true
#endregion
#region Private m_Variables
private TcpClient m_Client
private NetworkStream m_NetStream = null
private byte[] m_Buffer = new byte[2048]
private NetworkStream m_OutStream
[Tooltip("This value should be >= to Server waitingMessagesFrequency")]
[Min(0)] private float m_DelayedCloseTime = 0.5f
#endregion
#region Delegate Variables
protected Action OnClientStarted = null //Delegate triggered when client start
protected Action OnClientClosed = null//Delegate triggered when client close
#endregion
private void Awake()
{
if (Instance == null)
Instance = this
}
//Start client and stablish connection with server
public void StartClient()
{
//Early out
if (m_Client != null)
{
ClientLogError($"There is already a runing client on {ipAdress}::{port}")
return
}
try
{
//Create new client
m_Client = new TcpClient()
//Set and enable client
m_Client.BeginConnect(ipAdress, port, new AsyncCallback(OnConnect), null)
ClientLogInfo($"Client Started on {ipAdress}::{port}")
OnClientStarted?.Invoke()
}
catch (SocketException)
{
ClientLogError("Socket Exception: Start Server first")
OnClose()
}
}
private void OnConnect(IAsyncResult asr)
{
ClientLogInfo("Connect Sucessful.")
m_NetStream = m_Client.GetStream()
m_Client.GetStream().BeginRead(m_Buffer, 0, m_Buffer.Length, new AsyncCallback(OnRead), m_Client)
}
#region Receive Message
private void OnRead(IAsyncResult result)
{
OnReceivedMessage(m_Buffer)
NetworkStream stream = m_Client.GetStream()
lock (stream)
{
Array.Clear(m_Buffer, 0, m_Buffer.Length)
m_Client.GetStream().BeginRead(m_Buffer, 0, m_Buffer.Length, new AsyncCallback(OnRead), m_Client)
}
}
private void OnReceivedMessage(byte[] bytes)
{
ByteBuffer buffer = new ByteBuffer(bytes)
OnRecieveMessageDeal(buffer, 0)
}
private void OnRecieveMessageDeal(ByteBuffer buffer, ushort length = 0)
{
// 判断传参length是否为0,如果不为0则代表非首次调用,不再取length值而使用传递的length
ushort nextLength
if(length != 0)
{
nextLength = length
}
else
{// 判断传参length是否为0,如果为0则为首次调用,直接取出length后进行处理
nextLength = buffer.ReadUInt16()
}
uint pId = buffer.ReadUInt32()
ClientLogInfo("Length:" + nextLength + ".id:" + pId)
byte[] bytes = buffer.ReadBytes(nextLength)
NetLogic(pId, bytes)
// 取出下一个length,如果为0则没有数据了,不为0则递归调用,并且传递已经取出的长度值
nextLength = buffer.ReadUInt16()
if (nextLength != 0)
{
OnRecieveMessageDeal(buffer, nextLength)
}
}
#endregion
#region Process
private void NetLogic(uint pid, byte[] bytes)
{
ClientLogInfo("Get Msg Id :" + pid)
if (pid == 1)
{
SyncPid syncPid = SyncPid.Parser.ParseFrom(bytes)
ClientLogInfo("sync pid:"+syncPid.Pid)
}
if (pid == 200)
{
BroadCast broadCast = BroadCast.Parser.ParseFrom(bytes)
ClientLogInfo("broadCast-pid:" + broadCast.Pid)
ClientLogInfo("broadCast-Tp:" + broadCast.Tp)
ClientLogInfo("broadCast-Position-x:" + broadCast.P.X)
ClientLogInfo("broadCast-Position-y:" + broadCast.P.Y)
ClientLogInfo("broadCast-Position-z:" + broadCast.P.Z)
ClientLogInfo("broadCast-Position-v:" + broadCast.P.V)
}
}
#endregion
#region Send Message
private void WriteMessage(byte[] message)
{
MemoryStream memoryStream2
MemoryStream memoryStream = memoryStream2 = new MemoryStream()
try
{
memoryStream.Position = 0L
BinaryWriter binaryWriter = new BinaryWriter(memoryStream)
ushort num = (ushort)message.Length
binaryWriter.Write(message)
binaryWriter.Flush()
if (m_Client != null &&this.m_Client.Connected)
{
byte[] array = memoryStream.ToArray()
m_OutStream.BeginWrite(array, 0, array.Length, new AsyncCallback(OnWrite), null)
}
else
{
ClientLogError("client.connected----->>false")
}
}
finally
{
if (memoryStream2 != null)
{
((IDisposable)memoryStream2).Dispose()
}
}
}
private void OnWrite(IAsyncResult r)
{
try
{
m_OutStream.EndWrite(r)
}
catch (Exception ex)
{
ClientLogError("OnWrite--->>>" + ex.Message)
}
}
public void SendMessage(ByteBuffer buffer)
{
this.SessionSend(buffer.ToBytes())
buffer.Close()
}
private void SessionSend(byte[] bytes)
{
this.WriteMessage(bytes)
}
#endregion
#region Close Client
//Close client connection
public void Close()
{
if (m_Client != null)
{
if (m_Client.Connected)
{
m_Client.Close()
}
m_Client = null
}
loggedIn = false
}
public void OnClose()
{
ClientLogError("Client Closed")
//Reset everything to defaults
if (m_Client.Connected)
m_Client.Close()
if (m_Client != null)
m_Client = null
OnClientClosed?.Invoke()
}
#endregion
#region ClientLog
// Custom Client Log With Text Color
public void ClientLogInfo(string msg)
{
if (FullLog)
{
Debug.Log($"<color=green>Client:</color>{msg}")
}
}
public void ClientLogWarning(string msg)
{
if (FullLog)
{
Debug.LogWarning($"<color=yellow>Client:</color>{msg}")
}
}
public void ClientLogError(string msg)
{
if (FullLog)
{
Debug.LogError($"<color=red>Client:</color>{msg}")
}
}
//Custom Client Log Without Text Color
public void ClientLog(string msg)
{
if (FullLog)
{
Debug.Log($"Client:{msg}")
}
}
#endregion
}
}
在服务端启动socket监听程序,客户端去连服务器的IP地址就行了!举例(手写伪代码) :
在服务器端
Socket sock=new Socket("8080")
while(true){
data = sock.getInputStream();
//data 转成String型的数据str
if("msg"。equals(str)){
//todo....
}
}
在客户端
public static void main(String[] args) {
Socket sock = new Socket("服务器IP", "8080")
BufferedOutputStream out = new BufferedOutputStream(sock.getOutputStream())
out.write("msg".getBytes())
out.flush()
}
之前写过这样的一个小程序,我发布在自己的博客上:http://www.zhouhaibing.com/blog/archive/8
Server.c
#include <WinSock2.h>#include <WS2tcpip.h>
#include <cstdio>
#include <iostream>
// for file read
#include <fstream>
#include <string>
int main() {
/* load the initializer library */
WSADATA wsaData
WSAStartup(MAKEWORD(2, 2), &wsaData)
/* list the each fields of wsaData */
// printf("wVersion: %d\n", wsaData.wVersion) // 514
// printf("wHighVersion: %d\n", wsaData.wHighVersion) // 514
// printf("iMaxSockets: %d\n", wsaData.iMaxSockets) // 0
// printf("iMaxUdpDg: %d\n", wsaData.iMaxUdpDg) // 0
/* you may not print the lpVendorInfo */
// printf("szDescription: %s\n", wsaData.szDescription) // WinSock 2.0
// printf("szSystemStatus: %s\n", wsaData.szSystemStatus) // Running
/* create socket(address family, type, protocol) */
int socket_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)
/* initialize the addrinfo hints */
struct addrinfo hints
memset(&hints, 0, sizeof(hints))
hints.ai_family = AF_INET
hints.ai_socktype = SOCK_STREAM
hints.ai_protocol = IPPROTO_TCP
hints.ai_flags = AI_PASSIVE
struct addrinfo *result = nullptr
/* by hints, and then get the result(a linked list, see fields below) */
getaddrinfo(NULL, "8080", &hints, &result)
/* the member fiekds of result */
// printf("ai_family: %d\n", result->ai_family) // 2
// printf("ai_socktype: %d\n", result->ai_socktype) // 1
// printf("ai_protocol: %d\n", result->ai_protocol) // 6
// printf("ai_flags: %d\n", result->ai_flags) // 0
// printf("ai_canonname: %s\n", result->ai_canonname) // (null)
// printf("ai_a ddrlen: %d\n", result->ai_addrlen) // 16
// printf("ai_addr->sa_family: %d\n", result->ai_addr->sa_family) // 2
// printf("ai_addr->sa_data: %s\n", result->ai_addr->sa_data) //
// printf("ai_next: %x\n", result->ai_next) // 0
/* bind the socket to a address */
/* bind(socket, sockaddr name, name len) */
bind(socket_fd, result->ai_addr, result->ai_addrlen)
freeaddrinfo(result)
/* listen the socket */
/* listen(socket, backlog) */
listen(socket_fd, SOMAXCONN) /* 0x7fffffff */
while(true) {
/* accept a connection */
/* accept(socket, addr, addrlen) */
int client_fd = accept(socket_fd, nullptr, 0)
printf("New Connection Eastablished...\n")
/* Now we send the source code of this file to client */
std::ifstream fin("c:\\source.cpp")
/* store it into a buffer. */
while (fin.good()) {
// I rememeber there is a method called getline
std::string s
getline(fin, s)
// we need a new line
s = s + '\n'
send(client_fd, s.c_str(), s.size(), 0)
}
fin.close()
/* close client socket */
closesocket(client_fd)
}
/* may be never invoked */
closesocket(socket_fd)
WSACleanup()
return 0
}
Client.c
#include <WinSock2.h>#include <cstdio>
#include <iostream>
#include <fstream>
int main() {
/* load the initializer library */
WSADATA wsaData
WSAStartup(MAKEWORD(2, 2), &wsaData)
/* create socket */
int socket_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)
/* connect */
sockaddr_in addr
addr.sin_family = AF_INET
addr.sin_addr.s_addr = inet_addr("127.0.0.1")
addr.sin_port = htons(8080)
/* connect(socket, sockaddr, namelen) */
connect(socket_fd, (sockaddr*)&addr, sizeof(addr))
/* buffer memory */
char buf[1024]
/* open a file for write */
std::ofstream fout("source.cpp", std::ios_base::trunc)
while (true) {
int read = recv(socket_fd, buf, 1024, 0)
if (read == 0) {
fout.close()
printf("Connection Closed...\n")
break
}
if (read > 1024) {
printf("Buffer Overflow...\n")
} else {
buf[read - 1] = 0
/* now we can print the bytes from server */
fout << buf << std::endl
}
}
/* close socket */
closesocket(socket_fd)
WSACleanup()
return 0
}
欢迎分享,转载请注明来源:夏雨云
评论列表(0条)