socket通信问题
2015年12月11日 14:55:04 yiqijinbu 阅读数:3035
TCP:面向连接的,所以在服务端绑定端口后,需要监听Listen()是否有客户端发送请求,有的话,Accept()建立一个新的socket对象,用于发送和接收信息,
就想先建造了一条高速路,再建造一辆货车拉货。
UDP:无连接的,所以在服务端绑定端口后,不需要监听Listen(),也不用建立一个新的socket对象用于接收发送信息,但是在发送和接收时,要讲本身的端口
做参数发送给对方,这样在交流时,对方才能确定自己。
UDP协议:
Client端:
static void Main(string[] args)
{
int port = 2001;
string strHost = GetAddressIP();// "127.0.0.1";
// 建立IP对象
IPAddress ip = IPAddress.Parse(strHost);
// 建立端口对象
IPEndPoint ipe = new IPEndPoint(ip, port);
// 创建socket对象
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
Console.WriteLine("连接中。。。");
// 向服务器发送消息
string strMsgToServe = "嗨,来自客户端的问候。。。";
// 转成二进制发送到服务端
byte[] bytMsgToServe = Encoding.UTF8.GetBytes(strMsgToServe);
socket.SendTo(bytMsgToServe, bytMsgToServe.Length, SocketFlags.None, ipe);
Console.WriteLine("消息已发送。。。");
//IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0);
EndPoint Remote = new IPEndPoint(IPAddress.Any, 0);//(EndPoint)sender;
bytMsgToServe = new byte[1024];
int recv = socket.ReceiveFrom(bytMsgToServe, ref Remote);//接受来自服务器的数据
Console.WriteLine("Message received from{0}:", Remote.ToString());
Console.WriteLine("收到的服务端消息:"+Encoding.UTF8.GetString(bytMsgToServe, 0, recv));
socket.Close();
Console.ReadLine();
}
/// <summary>
/// 获取本地IP地址信息
/// </summary>
public static string GetAddressIP()
{
///获取本地的IP地址
string AddressIP = string.Empty;
foreach (IPAddress _IPAddress in Dns.GetHostEntry(Dns.GetHostName()).AddressList)
{
if (_IPAddress.AddressFamily.ToString() == "InterNetwork")
{
AddressIP = _IPAddress.ToString();
}
}
return AddressIP;
}
Server端:
static void Main(string[] args)
{
int port = 2001;
string strHost = GetAddressIP();// "127.0.0.1";
// 创建终结点
IPAddress ip = IPAddress.Parse(strHost);
// 创建网络端口
IPEndPoint ipe = new IPEndPoint(ip, port);
// 创建socke,开始监听--SocketType枚举
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
// 绑定端口
socket.Bind(ipe);
Console.WriteLine("等待客户端连接。。。");
//IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0);//定义要发送的计算机的地址
EndPoint Remote = new IPEndPoint(IPAddress.Any, 0);//(EndPoint)(sender);
// 收到的二进制byte
byte[] bytRecv = new byte[1024];
int intBytes = socket.ReceiveFrom(bytRecv, ref Remote);//接受来自服务器的数据
//Console.WriteLine("Message received from{0}:", Remote.ToString());
Console.WriteLine("收到的信息:-"+Encoding.UTF8.GetString(bytRecv, 0, intBytes));
string welcome = "Welcome to my test server!";
bytRecv = Encoding.ASCII.GetBytes(welcome);
socket.SendTo(bytRecv, bytRecv.Length, SocketFlags.None, Remote);
Console.ReadLine();
}
/// <summary>
/// 获取本地IP地址信息
/// </summary>
public static string GetAddressIP()
{
///获取本地的IP地址
string AddressIP = string.Empty;
foreach (IPAddress _IPAddress in Dns.GetHostEntry(Dns.GetHostName()).AddressList)
{
if (_IPAddress.AddressFamily.ToString() == "InterNetwork")
{
AddressIP = _IPAddress.ToString();
}
}
return AddressIP;
}
当将服务层写成window服务时,如果客户端关闭,服务端会报错,“远程主机关闭了一个现有的链接”,然后整个服务都停止了。
解决办法:为socket对象设置低级操作模式
// 为 Socket 设置低级操作模式,不然当客户端关闭的时候,会报错
uint IOC_IN = 0x80000000;
uint IOC_VENDOR = 0x18000000;
uint SIO_UDP_CONNRESET = IOC_IN | IOC_VENDOR | 12;
socket.IOControl((int)SIO_UDP_CONNRESET, new byte[] { Convert.ToByte(false) }, null);
另外,在window服务中,定时控件是不能用的,但是也不报错,不提醒,如果要定时循环,
解决办法:
System.Timers.Timer tmrSelectCOM = new System.Timers.Timer(2000);
tmrSelectCOM.Elapsed += new System.Timers.ElapsedEventHandler(tmrSelectCOM_Tick);
tmrSelectCOM.Enabled = true;
TCP协议:
服务端:
static void Main(string[] args)
{
// ip地址,端口
int port = 2000;
string strIp = GetAddressIP();
// IP对象
IPAddress ip = IPAddress.Parse(strIp);
IPEndPoint ipe = new IPEndPoint(ip, port);
// 实例化socket对象
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
// 绑定端口
socket.Bind(ipe);
// 监听
socket.Listen(0);
// 为发送请求的客户端创建新的socket对象
Socket temp = socket.Accept();
// 接收消息
byte[] bytRecv = new byte[1024];
int intCount = temp.Receive(bytRecv,bytRecv.Length,0);
string strRecv = Encoding.UTF8.GetString(bytRecv, 0, intCount);
Console.WriteLine(strRecv);
// 发送消息
string strSendMsg = "来自服务端的问候。。。";
byte[] bytSendMsg = Encoding.UTF8.GetBytes(strSendMsg);
temp.Send(bytSendMsg, 0, bytSendMsg.Length, 0);
Console.WriteLine("服务端消息已发送。。。");
Console.ReadLine();
}
private static string GetAddressIP()
{
string strAddressIP = string.Empty;
foreach (IPAddress address in Dns.GetHostEntry(Dns.GetHostName()).AddressList)
{
if (address.AddressFamily.ToString() == "InterNetwork")
{
strAddressIP = address.ToString();
}
}
return strAddressIP;
}
- 客户端:
public static void Main(string[] args)
{
int port = 2000;
string strIp = GetAddressIP();
// IP对象
IPAddress ip = IPAddress.Parse(strIp);
IPEndPoint ipe = new IPEndPoint(ip, port);
// 创建socket对象
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
// 连接
socket.Connect(ipe);
Console.WriteLine("已连接。。。");
// 发送信息
string strSendMsg="来自客户端的问候。。。";
byte[] bytSendMsg = Encoding.UTF8.GetBytes(strSendMsg);
socket.Send(bytSendMsg, 0, bytSendMsg.Length, SocketFlags.None);
Console.WriteLine("消息已发送。。。");
// 接收
byte[] bytRecvMsg = new byte[1024];
int intCount = socket.Receive(bytRecvMsg);
string strRecvMsg = Encoding.UTF8.GetString(bytRecvMsg, 0, intCount);
Console.WriteLine(strRecvMsg);
Console.ReadLine();
}
private static string GetAddressIP()
{
// 获取本地的IP地址
string AddressIP = string.Empty;
foreach (IPAddress _IPAddress in Dns.GetHostEntry(Dns.GetHostName()).AddressList)
{
if (_IPAddress.AddressFamily.ToString() == "InterNetwork")
{
AddressIP = _IPAddress.ToString();
}
}
return AddressIP;
}
TCP图:
UDP图: