服务器端的整体思路:

1、初始化IP地址和端口号以及套接字等字段;

2、绑定IP启动服务器,开始监听消息  socketServer.Listen(10);

3、开启一个后台线程接受客户端的连接 socketServer.Accept(),这里需要注意的是服务器端有两个Socket,一个负责监听,另一个负责传输消息,分工明确;

4、接受客户端消息  socketMsg.Receive();

5、向客户端发送消息 Send(bySendArray);

6、当然还应该包括信息显示方法和系统的退出方法。

/***
*
*
* 服务器端
*
*/ using System.Collections;
using System.Collections.Generic;
using UnityEngine; using System.Text;
using System.Threading;
using System.Net;
using System.Net.Sockets;
using UnityEngine.UI;
using System; public class Server : MonoBehaviour
{
public InputField InpIPAdress; //IP地址
public InputField InpPort; //端口号
public InputField InpDisplayInfo; //显示信息
public InputField InpSendMsg; //发送信息
public Dropdown Dro_IPList; //客户端的IP列表 private Socket socketServer; //服务端套接字
private bool IsListionContect = true; //是否监听
private StringBuilder _strDisplayInfo = new StringBuilder();//追加信息
private string _CurClientIPValue = string.Empty; //当前选择的IP地址
//保存客户端通讯的套接字
private Dictionary<string, Socket> _DicSocket = new Dictionary<string, Socket>();
//保存DropDown的数据,目的为了删除节点信息
private Dictionary<string, Dropdown.OptionData> _DicDropdowm = new Dictionary<string, Dropdown.OptionData>(); // Start is called before the first frame update
void Start()
{
//控件初始化
InpIPAdress.text = "127.0.0.1";
InpPort.text = "";
InpSendMsg.text = string.Empty; //下拉列表处理
Dro_IPList.options.Clear(); //清空列表信息
//添加一个空节点
Dropdown.OptionData op = new Dropdown.OptionData();
op.text = "";
Dro_IPList.options.Add(op);
} /// <summary>
/// 退出系统
/// </summary>
public void ExitSystem()
{
//退出会话Socket //退出监听Socket
if (socketServer != null)
{
try
{
socketServer.Shutdown(SocketShutdown.Both); //关闭连接
}
catch (Exception)
{ throw;
}
socketServer.Close(); //清理资源
}
Application.Quit();
} /// <summary>
/// 获取当前好友
/// </summary>
public void GetCurrentIPInformation()
{
//选择玩家当前列表
_CurClientIPValue = Dro_IPList.options[Dro_IPList.value].text;
} /// <summary>
/// 服务端开始监听
/// </summary>
public void EnableServerReady()
{
//需要绑定地址和端口号
IPEndPoint endPoint = new IPEndPoint(IPAddress.Parse(InpIPAdress.text), Convert.ToInt32(InpPort.text));
//定义监听Socket
socketServer = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//绑定
socketServer.Bind(endPoint); //开始socket监听
socketServer.Listen();
//显示内容
DisplayInfo("服务器端启动"); //开启后台监听(监听客户端连接)
Thread thClientCon = new Thread(ListionCilentCon);
thClientCon.IsBackground = true; //后台线程
thClientCon.Name = "thListionClientCon";
thClientCon.Start();
} /// <summary>
/// 接听到客户端的连接
/// </summary>
private void ListionCilentCon()
{
Socket socMesgServer = null; //会话Socket try
{
while (IsListionContect)
{
//等待接受客户端连接,此处会“阻断”当前线程
socMesgServer = socketServer.Accept();
//获取远程节点信息
string strClientIPAndPort = socketServer.RemoteEndPoint.ToString();
//把远程节点信息添加到DropDown控件中
Dropdown.OptionData op = new Dropdown.OptionData();
op.text = strClientIPAndPort;
Dro_IPList.options.Add(op);
//把会话Socket添加到集合中(为后面发送信息使用)
_DicSocket.Add(strClientIPAndPort, socMesgServer);
//控件显示,有客户端连接
DisplayInfo("有客户端连接"); //开启后台线程,接受客户端信息
Thread thClientMsg = new Thread(ReceivMsg);
thClientMsg.IsBackground = true;
thClientMsg.Name = "thListionClientMsg";
thClientMsg.Start(socMesgServer);
}
}
catch (Exception)
{
IsListionContect = false;
//关闭会话Socket
if (socketServer != null)
{
socketServer.Shutdown(SocketShutdown.Both);
socketServer.Close();
}
if (socMesgServer != null)
{
socMesgServer.Shutdown(SocketShutdown.Both);
socMesgServer.Close();
}
}
} /// <summary>
/// 后台线程,接受客户端信息
/// </summary>
/// <param name="sockMsg"></param>
private void ReceivMsg(object sockMsg)
{
Socket socketMsg = sockMsg as Socket; try
{
while (true)
{
//准备接受数据缓存
byte[] msgAarry = new byte[ * ];
//准备接受客户端发来的套接字信息
int trueClientMsgLenth = socketMsg.Receive(msgAarry);
//byte数组转换为字符串
string strMsg = System.Text.Encoding.UTF8.GetString(msgAarry, , trueClientMsgLenth);
//显示接受的客户端消息内容
DisplayInfo("客户端消息:" + strMsg);
}
}
catch (Exception)
{
}
finally
{
DisplayInfo("有客户端断开连接了:" + socketMsg.RemoteEndPoint.ToString()); //字典类断开连接的客户端消息
_DicSocket.Remove(socketMsg.RemoteEndPoint.ToString());
//客户端列表移除
if (_DicDropdowm.ContainsKey(socketMsg.RemoteEndPoint.ToString()))
{
Dro_IPList.options.Remove(_DicDropdowm[socketMsg.RemoteEndPoint.ToString()]);
}
//关闭Socket
socketMsg.Shutdown(SocketShutdown.Both);
socketMsg.Close();
} } //向发送客户端会话
public void SendMsg()
{
//参数检查
_CurClientIPValue = _CurClientIPValue.Trim();
if (string.IsNullOrEmpty(_CurClientIPValue))
{
DisplayInfo("请选择要聊天的用户名称");
return;
} //判断是否与指定的Socket通信
if (_DicSocket.ContainsKey(_CurClientIPValue))
{
//得到发送的消息
string strSendMsg = InpSendMsg.text;
strSendMsg = strSendMsg.Trim(); if (!string.IsNullOrEmpty(strSendMsg))
{
//信息转码
byte[] bySendArray = System.Text.Encoding.UTF8.GetBytes(strSendMsg);
//发送数据
_DicSocket[_CurClientIPValue].Send(bySendArray);
//记录发送数据
DisplayInfo("发送的数据:" + strSendMsg); //控件重置
InpSendMsg.text = string.Empty;
}
else
{
DisplayInfo("发送的消息不能为空!");
}
}
else
{
DisplayInfo("请选择合法的聊天用户!");
} } /// <summary>
/// 主显示控件,显示消息
/// </summary>
/// <param name="str"></param>
private void DisplayInfo(string str)
{
str = str.Trim();
if (!string.IsNullOrEmpty(str))
{
_strDisplayInfo.Append(System.DateTime.Now.ToString());
_strDisplayInfo.Append(" ");
_strDisplayInfo.Append(str);
_strDisplayInfo.Append("\r\n");
InpDisplayInfo.text = _strDisplayInfo.ToString();
}
} // Update is called once per frame
void Update()
{ }
}

客户端整体思路:

1、初始化IP地址和端口号以及一些显示信息和套接字;

2、启动客户端连接 _SockClient.Connect(endPoint);

3、开启后台线程监听客户端发来的信息 _SockClient.Receive(byMsgArray);

4、客户端发送数据到服务器  _SockClient.Send(byteArray);

5、当然也应该包括退出系统和显示信息方法。

/***
*
*
*
* 客户端
*
*
*/
using System.Collections;
using System.Collections.Generic;
using UnityEngine; using System;
using System.Threading;
using System.Net;
using System.Net.Sockets;
using System.Text;
using UnityEngine.UI; public class Client : MonoBehaviour
{
public InputField InpIPAdress; //IP地址
public InputField InpPort; //端口号
public InputField InpDisplayInfo; //显示信息
public InputField InpSendMsg; //发送信息 private Socket _SockClient; //客户端Socket
private IPEndPoint endPoint;
private bool _IsSendDataConnection=true; //发送数据连接
private StringBuilder _SbDisplayInfo = new StringBuilder();//控件追加信息 // Start is called before the first frame update
void Start()
{
InpIPAdress.text = "127.0.0.1";
InpPort.text = "";
} //客户端退出系统
public void ExitSystem()
{
//关闭客户端Socket
if (_SockClient != null)
{
try
{
//关闭连接
_SockClient.Shutdown(SocketShutdown.Both);
}
catch
{
}
//清理资源
_SockClient.Close();
} //退出
Application.Quit(); } //启动客户端连接
public void EnableClientCon()
{
//通讯IP和端口号
endPoint = new IPEndPoint(IPAddress.Parse(InpIPAdress.text), Convert.ToInt32(InpPort.text));
//建立客户端Socket
_SockClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); try
{
//建立连接
_SockClient.Connect(endPoint);
//启动线程,监听服务端返回的消息
Thread thrListenMsgFromServer = new Thread(ListionMsgFromServer);
thrListenMsgFromServer.IsBackground = true;
thrListenMsgFromServer.Name = "thrListenMsgFromServer";
thrListenMsgFromServer.Start();
}
catch (Exception)
{ throw;
}
//控件显示连接服务端成功
DisplayInfo("连接服务器成功!"); } /// <summary>
/// 后台线程监听服务端返回的消息
/// </summary>
public void ListionMsgFromServer()
{
try
{
while (true)
{
//开辟消息内存区域
byte[] byMsgArray = new byte[ * ];
//客户端接受服务器返回的数据
int intTrueMsgLengh = _SockClient.Receive(byMsgArray);
//转化为字符串
string strMsg = System.Text.Encoding.UTF8.GetString(byMsgArray, , intTrueMsgLengh);
//显示收到的消息
DisplayInfo("服务器返回消息:" + strMsg);
}
}
catch
{
}
finally
{
DisplayInfo("服务器断开连接");
_SockClient.Disconnect(true);
_SockClient.Close();
} } //客户端发送数据到服务器
public void SendMsg()
{
string strSendMsg = InpSendMsg.text;
if (!string.IsNullOrEmpty(strSendMsg))
{
//字节转化
byte[] byteArray = System.Text.Encoding.UTF8.GetBytes(strSendMsg);
//发送
_SockClient.Send(byteArray);
//显示发送内容
DisplayInfo("我:" + strSendMsg); //控件清空
InpSendMsg.text = string.Empty;
}
else
{
DisplayInfo("提示:发送信息不能为空!");
}
} /// <summary>
/// 主显示控件,显示消息
/// </summary>
/// <param name="str"></param>
private void DisplayInfo(string str)
{
str = str.Trim();
if (!string.IsNullOrEmpty(str))
{
_SbDisplayInfo.Append(System.DateTime.Now.ToString());
_SbDisplayInfo.Append(" ");
_SbDisplayInfo.Append(str);
_SbDisplayInfo.Append("\r\n");
InpDisplayInfo.text = _SbDisplayInfo.ToString();
}
} // Update is called once per frame
void Update()
{ }
}

Unity 网络编程(Socket)应用的更多相关文章

  1. 网络编程socket基本API详解(转)

    网络编程socket基本API详解   socket socket是在应用层和传输层之间的一个抽象层,它把TCP/IP层复杂的操作抽象为几个简单的接口供应用层调用已实现进程在网络中通信. socket ...

  2. Android 网络编程 Socket

    1.服务端开发 创建一个Java程序 public class MyServer { // 定义保存所有的Socket,与客户端建立连接得到一个Socket public static List< ...

  3. 网络编程Socket之TCP之close/shutdown具体解释(续)

    接着上一篇网络编程Socket之TCP之close/shutdown具体解释 如今我们看看对于不同情况的close的返回情况和可能遇到的一些问题: 1.默认操作的close 说明:我们已经知道writ ...

  4. 铁乐学Python_Day33_网络编程Socket模块1

    铁乐学Python_Day33_网络编程Socket模块1 部份内容摘自授课老师的博客http://www.cnblogs.com/Eva-J/ 理解socket Socket是应用层与TCP/IP协 ...

  5. Python网络编程socket

    网络编程之socket 看到本篇文章的题目是不是很疑惑,what is this?,不要着急,但是记住一说网络编程,你就想socket,socket是实现网络编程的工具,那么什么是socket,什么是 ...

  6. java网络编程socket\server\TCP笔记(转)

    java网络编程socket\server\TCP笔记(转) 2012-12-14 08:30:04|  分类: Socket |  标签:java  |举报|字号 订阅     1 TCP的开销 a ...

  7. linux网络编程-socket(37)

    在编程的时候需要加上对应pthread开头的头文件,gcc编译的时候需要加了-lpthread选项 第三个参数是线程的入口参数,函数的参数是void*,返回值是void*,第四个参数传递给线程函数的参 ...

  8. python网络编程-socket编程

     一.服务端和客户端 BS架构 (腾讯通软件:server+client) CS架构 (web网站) C/S架构与socket的关系: 我们学习socket就是为了完成C/S架构的开发 二.OSI七层 ...

  9. Python开发【第八篇】:网络编程 Socket

    Socket socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄,应用程序通常通过"套接字"向网络发出请求或者应答网络请求. sock ...

随机推荐

  1. python设计模式第六天【原型模式】

    1.定义 使用原型模式复制的对象与原来对象具有一样的结构和数据,有浅克隆和深克隆 2.应用场景 (1)希望复制原来对象的结构和数据胆步影响原来对象 3.代码实现 #!/usr/bin/env pyth ...

  2. JQuery operate xml

    msg is <?xml ?> <Parameters> <WorkflowName>...</WorkflowName> </Parameter ...

  3. Tunnel Warfare(线段树取连续区间)

    emmmmmmmm我菜爆了 思路来自:https://blog.csdn.net/chudongfang2015/article/details/52133243 线段树最难的应该就是要维护什么东西 ...

  4. c++ 怎么输出保留2位小数的浮点数

    //添加头文件 #include<iomanip> //定义变量 folat a=9.1; cout<<setiosflags(ios::fixed)<<setpr ...

  5. JavaScript的 sourcemap 的理解

    当我们在使用vue-cli 开发项目完成后, 就要进行部署,执行npm run build 命令,你会发现它生成.js文件的同时,还会生成一个对应的.map 文件. 当时查了一下, .map 文件的主 ...

  6. Wiener Filter

    假设分别有两个WSS process:$x[n]$,$y[n]$,这两个process之间存在某种关系,并且我们也了解这种关系.现在我们手头上有process $x[n]$,目的是要设计一个LTI系统 ...

  7. BZOJ4755 [JSOI2016]扭动的回文串 【后缀数组】【manacher】

    题目分析: 我写了史上最丑的后缀数组,怎么办? 首先manacher一遍两个串,这样只用考虑第三问.用$作为间隔符拼接两个串,把第一个串翻转.枚举回文中心,取最长的回文串,对于剩下的部分利用LCP匹配 ...

  8. UOJ272 [清华集训2016] 石家庄的工人阶级队伍比较坚强 【分治乘法】

    题目分析: 首先不难注意到式子就是异或卷积,所以考虑用分治乘法推出优化方法.我们把一个整体$f$拆成$f-,f\pm,f+$,然后另一个拆成$g-,g\pm,g+$.这样做的好处是能更清楚的分析问题. ...

  9. gogs : 添加 ssh An error has occurred : addKey: fail to parse public key: exec: "ssh-keygen": executable file not found in %PATH% - exec: "ssh-keygen": executable file not found in %PATH%

    服务器上缺少配置   ssh-keygen.exe的 环境变量.git的环境变量 在path 环境变量加上.重启gogs服务

  10. MT【189】二次条件配方

    “当一幢建筑物完成时,应该把脚手架拆除干净.”——高斯 (2017北大特优)若对任意使得关于 \(x\) 的方程 \(ax^2+bx+c=0\)(\(ac\ne 0\))有实数解的 \(a,b,c\) ...