Socket 客户端与服务器的架构初步构想
构想着使用Socket来维持多个客户端和服务器保持着长连接。
先分享一篇不错的socket的文章
Linux Socket过程详细解释(包括三次握手建立连接,四次握手断开连接)
近期一直在考虑如何做一个多人同时在线的游戏,对于服务器这一块肯定是需要用到socket的,于是先将游戏想的简单一点,比如,这个多人在线的游戏是一个打麻将的,那么只需要最多先支持4个人同时在线就行了,那么服务器要做的事情有:
- 跟多台客户端保持着长连接(多人同时在线)
- 将一些信息同时发给每个客户端(洗牌)
- 将某个客户端发送给服务器的消息传递给其它的客户端(出牌)
那么我先需要的是一个支持多人连接的socket服务器,然后我要将每个新增的连接存起来,并且能够在任意情况下对这个连接的客户端发送消息,服务器代码如下:
服务端:C#控制台程序
using System;
using System.Net.Sockets;
using System.Net;
using System.Threading;
using System.Text;
namespace socket
{
class MainClass
{
static byte[] result = new byte[1024];//接收数据
static int myProt = 9527; //端口
static string socketip = "127.0.0.1";
static Socket serverSocket; //socket对象
static object[] collectArray = new object[4];//连接对象池
public static void Main(string[] args)
{
//服务器IP地址
IPAddress ip = IPAddress.Parse(socketip);
//创建服务端socket对象
serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//绑定IP地址:端口
serverSocket.Bind(new IPEndPoint(ip, myProt));
//设定最多连接
serverSocket.Listen(collectArray.Length);
Console.WriteLine("启动监听【{0}】成功", serverSocket.LocalEndPoint.ToString());
//监听线程
Thread myThread = new Thread(ListenClientConnect);
//启动监听
myThread.Start();
}
///
/// 监听客户端连接
///
private static void ListenClientConnect()
{
while (true)
{
Socket clientSocket = serverSocket.Accept();
string say = "Server Say Hello";
clientSocket.Send(Encoding.Default.GetBytes(say),say.Length,0);
Thread receiveThread = new Thread(ReceiveMessage);
//创建连接对象,并加入collect池中
for (int i = 0; i < collectArray.Length; i++)
{
if (collectArray[i] == null)
{
CollectObject collect = new CollectObject();
collect.t_socket = clientSocket;
collect.t_index = i;
collect.t_userid = "tid_" + i;
collectArray[i] = collect;
receiveThread.Start(i);
Console.WriteLine("新增链接【{0}】", collect.t_userid);
break;
}
}
}
}
///
/// 接收消息
///
///
private static void ReceiveMessage(object index)
{
CollectObject Mycollect = collectArray[Convert.ToInt32(index)] as CollectObject;
while (true)
{
try
{
//通过clientSocket接收数据
int receiveNumber = Mycollect.t_socket.Receive(result, result.Length, 0);
byte[] bt = Encoding.Convert(Encoding.UTF8, Encoding.Unicode, result, 0, receiveNumber);
string content = Encoding.Unicode.GetString(bt);
Console.WriteLine("接收消息:【{0}】",content);
sendData(Mycollect.t_socket, content);
}
catch
{
//关闭连接
Mycollect.t_socket.Close();
Console.WriteLine("链接【{0}】已断开",Mycollect.t_userid);
//从连接池中删除
collectArray[Convert.ToInt32(index)] = null;
break;
}
}
}
///
/// 发送数据
///
/// 客服端socket对象
/// 消息内容
private static void sendData(Socket clientSocket,string message)
{
//发送消息给服务器
string responStr = "";
if (message == "a")
{
responStr = "尼玛";
}
else if (message == "b")
{
responStr = "这是密码呀";
}
else if (message == "c")
{
responStr = "为所欲为";
}
else
{
responStr = "别以为你发了个("+message+")我就要回复你,滚粗~~~";
}
byte[] responBTs = Encoding.Default.GetBytes(responStr);
clientSocket.Send(responBTs, responBTs.Length, 0);
Console.WriteLine("发送消息:【{0}】", responStr);
}
}
///
/// 链接对象
///
class CollectObject
{
///
/// socket对象
///
public Socket t_socket { get; set;}
///
/// 连接池下标
///
public int t_index { get; set; }
///
/// 用户ID
///
public string t_userid { get; set; }
}
}
这个简单的服务器最多支持4个客户端同时连接,使用一个固定长度的全局数组和自定义了一个连接对象的类,将每一个新增的连接创建为一个连接对象保存在数组中,然后任意一个客户端发送消息触发某些操作时,或者服务器需要广播消息,都可以通过这个数组将将消息传递给其它客户端,这里的每一个连接都有一个单独线程,安全性有待下一步将客户端做好之后再来实验一下。
Next 使用cocoa2d来开发一个麻将游戏
END