您的位置:首页 > 理论基础 > 计算机网络

Socket 基础&实例(上)

2016-02-23 23:34 671 查看

Socket 基础知识

TCP/IP层次模型

a. 应用层

b. 传输层 : UDP和TCP(区别即 TCP传输控制协议,是一种提供可靠数据传输的通用协议。

     UDP是一个面 向无连接的协议,此处可能解释不太清楚,百度哈。(~ o ~)~zZ)

c. 网络层:通信子网,它通过网络连接交换传输层发出的实体数据。

d. 链路层:是建立在物理传输能力的基础上,以帧为单位传输数据,

     它的主要任务就是进行数据封装和数据链接的建立

TCP分节传输图解



(每层传输过程中,都将增加分节的头)

Socket类型

a. 流式Socket

 是一种面向连接的Socket,针对于面向连接的TCP服务应用,安全,但是效率低

b. 数据报式Socket

 是一种无连接的Socket,对应于无连接的UDP服务应用,不安全,但效率高

 组图说明Socket客户端和服务器的连接过程



这就是所谓的三次握手,哈哈。。

Socket常用类和方法

相关类:

IPAddress:包含了一个IP地址
IPEndPoint:包含了一对IP地址和端口号


方法:

Socket():创建一个Socket
Bind():绑定一个本地的IP和端口号(IPEndPoint)
Listen():让Socket侦听传入的连接吃那个病,并指定侦听队列容量
Connect():初始化与另一个Socket的连接
Accept():接收连接并返回一个新的Socket
Send():输出数据到Socket
Receive():从Socket中读取数据


上方法在Socket连接中基本上都会用到

实战部分代码

服务器代码(新建项目的时候,此处是




using System;
using System.Net;
using System.Collections.Generic;
using System.Net.Sockets;
using System.IO;
using System.Text;
using System.Threading;
using System.Runtime.Serialization.Formatters.Binary;

public class Echoserver
{
private static int m_SocketCount = 0;

private static ManualResetEvent m_ManualResetEvent = new ManualResetEvent(false);

//entry point of main method.
public static void Main()
{
IPEndPoint ipEndPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 10068);

Socket serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

try
{
serverSocket.Bind(ipEndPoint);
serverSocket.Listen(20);
Console.WriteLine("Server Start");
while (true)
{
m_ManualResetEvent.Reset(); //将线程置于非终止状态,也就是等待当前线程完成;
serverSocket.BeginAccept(new AsyncCallback(Accept), serverSocket);
m_ManualResetEvent.WaitOne(); //阻塞主线程,这里的作用是不退出程序;
}
}
catch (System.Exception ex)
{
Console.WriteLine("Exception" + ex);
}
}

public static void Accept(IAsyncResult result)
{
m_ManualResetEvent.Set(); //通知主线程继续;

Socket serverSocket = (Socket)result.AsyncState;

Console.WriteLine("Accept one Client " + (++m_SocketCount));

//已经Accept客户端之后就停止Accept;
Socket receiverSocket = serverSocket.EndAccept(result);

//开始Receive;
StateObject state = new StateObject();
state.m_CurSocket = receiverSocket;
receiverSocket.BeginReceive(state.m_Buffer, 0, StateObject.m_BufferSize, 0, new AsyncCallback(ReceiveCallBack), state);
}

public static void ReceiveCallBack(IAsyncResult result)
{
String content = String.Empty;
StateObject state = (StateObject)result.AsyncState;
Socket receiverSocket = state.m_CurSocket;
try
{
int byteRead = receiverSocket.EndReceive(result);

if (byteRead > 0)
{
//获取数据长度;
byte[] datalengtharr = new byte[4];
Buffer.BlockCopy(state.m_Buffer, 0, datalengtharr, 0, 4);
int datalength = BitConverter.ToInt32(datalengtharr, 0);
Console.WriteLine("receive data length = " + datalength.ToString());

//获取数据主体;
byte[] dataarr = new byte[byteRead - 4];
Buffer.BlockCopy(state.m_Buffer, 4, dataarr, 0, byteRead - 4);
state.m_StringBuilder.Append(Encoding.ASCII.GetString(dataarr, 0, byteRead - 4));

content = state.m_StringBuilder.ToString();

//判断数据长度,是否接收完全;
if (!(byteRead - 4 < datalength))
{
Console.WriteLine("Receive " + content.Length + "  " + content);

//接收完全后发送数据给客户端;
Send(receiverSocket, "success from server");
}
else
{
//数据没有接收完,继续接收;
receiverSocket.BeginReceive(state.m_Buffer, 0, StateObject.m_BufferSize, 0, new AsyncCallback(ReceiveCallBack), state);
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}

}

public static void Send(Socket handler, String data)
{
byte[] byteData = Encoding.ASCII.GetBytes(data);
try
{
handler.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallback), handler);
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}

}

public static void SendCallback(IAsyncResult result)
{
try
{
Socket handler = (Socket)result.AsyncState;
int bytesSend = handler.EndSend(result);

Console.WriteLine("Sent {0} bytes to client.", bytesSend);

handler.Shutdown(SocketShutdown.Both);

handler.Close();
}
catch (System.Exception ex)
{
Console.WriteLine(ex.ToString());
}
}

public class StateObject
{
public Socket m_CurSocket = null;
public const int m_BufferSize = 1024;
public byte[] m_Buffer = new byte[m_BufferSize];
public StringBuilder m_StringBuilder = new StringBuilder();
}
}


客户端代码

using UnityEngine;
using UnityEngine.UI;
using System.Collections;
using System.Collections.Generic;
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.Serialization;

public class Test : MonoBehaviour
{
/// <summary>
/// 连接到服务器
/// </summary>
public void AsynConnect()
{
//端口及IP
IPEndPoint ipe = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 10068);
//创建套接字
Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//开始连接到服务器
client.BeginConnect(ipe, asyncResult =>
{
client.EndConnect(asyncResult);
//向服务器发送消息
DataMsg msg = new DataMsg();
msg.indexPos = 5;
msg.name = "宏宇";
msg.sex = 1;
List<string> otherPerList = new List<string>();
otherPerList.Add("小鸭");
otherPerList.Add("斗鸡");
otherPerList.Add("斗鸟");
msg.otherPerList.AddRange(otherPerList);

//AsynSend(client, msg);
AsynSend(client, "你好我是客户端");
//AsynSend(client, "第一条消息");
//AsynSend(client, "第二条消息");
//接受消息
AsynRecive(client);
}, null);
}

/// <summary>
/// 发送消息
/// </summary>
/// <param name="socket"></param>
/// <param name="message"></param>
public void AsynSend(Socket socket, string message)
{
if (socket == null || message == string.Empty) return;
//编码
byte[] data = Encoding.UTF8.GetBytes(message);
try
{
socket.BeginSend(data, 0, data.Length, SocketFlags.None, asyncResult =>
{
//完成发送消息
int length = socket.EndSend(asyncResult);
Debug.Log(string.Format("客户端发送消息:{0}", message));
}, null);
}
catch (Exception ex)
{
Debug.Log(string.Format("异常信息:{0}", ex.Message));
}
}

public void AsynSend(Socket socket, DataMsg msgData)
{
if (socket == null || msgData == null)
{
return;
}
Debug.Log(msgData);
MemoryStream mStream = new MemoryStream();
//BinaryFormatter bFormatter = new BinaryFormatter();
BinaryFormatter iFormatter = new BinaryFormatter();
//bFormatter.Serialize(mStream, msgData);
//bFormatter.Serialize(mStream, "fff");
iFormatter.Serialize(mStream, msgData);
mStream.Flush();
byte[] buffer = new byte[1024];
mStream.Position = 0;
while (mStream.Read(buffer, 0, buffer.Length) > 0)
{
socket.Send(buffer);
}
socket.Close();
Debug.Log("数据发送完毕");

}

/// <summary>
/// 接收消息
/// </summary>
/// <param name="socket"></param>
public void AsynRecive(Socket socket)
{
byte[] data = new byte[1024];
try
{
//开始接收数据
socket.BeginReceive(data, 0, data.Length, SocketFlags.None,
asyncResult =>
{
int length = socket.EndReceive(asyncResult);
Debug.Log(string.Format("收到服务器消息:{0}", Encoding.UTF8.GetString(data)));
//AsynRecive(socket);
}, null);
}
catch (Exception ex)
{
Debug.Log(string.Format("异常信息:", ex.Message));
}
}

void Awake()
{
gameObject.GetComponent<Button>().onClick.AddListener(delegate()
{
OnClickEvent(gameObject);
});
}

void OnClickEvent(GameObject target)
{
Debug.Log("Click" + target.name);
AsynConnect();
}

}

[Serializable]
public class DataMsg
{
public int indexPos;
public int sex;
public string name;
public List<string> otherPerList;
public DataMsg()
{
indexPos = 0;
sex = 0;
name = string.Empty;
otherPerList = new List<string>();
}
}


大家可能也注意到了我这里的客户端,留有传序列化的数据的方法,没错,本次实验只做传输数据,字符串简单的数据,后面会涉及多终端对一个服务器时的数据传输,等等,一直研究下去

如果有错误的地方,请指点,比较晚了,不好的下次再更新
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  socket 网络 通信 Unity