socket简单的访问流程
最近看了一些关于socket的东西,感觉蛮好用的,现把socket的简单通讯步骤记起来,以便学习:
1、新建Socket
Socket s = new Socket(AddressFamily addressFamily,SocketType socketType,ProtocolType protocolType)。
如:Socket s = new Soc ket(AddressFamily.InterNetw ork, SocketType.Stream, ProtocolType.Tcp);
//当然还可以是其他协议类型,如udp
Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
注:stream socket是面向连接的,打开之后的通讯过程必须始终保持连接。数据传输是可靠的,假如发送方发送“1,2”两个包,则接收方也会以相同的顺序接 接收到两个包,且保证数据的正确性,它是基于tcp协议传输的。dgram socket是非面向连接,如果发送方发送一个包,不需要事先建立连接,发送方的数据不能保证收到,即使收到了也不能保证以相同的顺序收到,但是能保证每个包数据的完整性,就像一封电报,它通过udp协议完成。
2、通过 Connect 方法连接到指定的服务器。
有Connect就肯定要有东西让它去connect啦,这就是IPEndPoint。IPEndPoint 类包含应用程序连接到主机上的服务所需的主机和端口信息,通过组合服务的主机 IP 地址和端口号,IPEndPoint 类形成连接到服务的连接点。 (在 Internet 中,TCP/IP 使用 一个网络地址和一个服务端口号来唯一标识设备)
如:IPEndPoint ipe = new IPEndPoint(IPAddress address, int port);
如何获取IPAddress呢?.net有两种类来处理:
(1)IPAddress 类:IPAddress 类包含计算机在 IP 网络上的地址。其 Parse 方法可将 IP地址字符串转换为 IPAddress 实例。下面的语句创建一IPAddress 实例:IPAddress myIP = IPAddress.Parse("192.168.1.2");
(2)Dns 类:向使用 TCP/IP Internet 服务的应用程序提供域名服务。其 Resolve 方法查询 DNS 服务器以将用户友好的域名(如www.cnblogs.com)映射到数字形式的 Internet 地址(61.155.169.116)。Resolve 方法 返回一个 IPHostEnty 实例,该实例包含所请求名称的地址和别名的列表。大多数情况下,可以使用 AddressList 数组中返回的第一个地址。下面的代码获取一个 IPAddress 实例,该实例包含服务器 www.cnblogs.com 的 IP 地址。
如:IPHostEntry ihe = Dns.Resolve("www.cnblogs.com");
IPAddress iar = ihe.AddressList[0];
也可以使用 GetHostName 方法得到 IPHostEntry 实例:
IPHosntEntry ihe=Dns.GetHostByName("www.cnblogs.com")
知道了上面的知识后,我们很容易就知道怎么连接服务器了吧:
IPAddress myIP = IPAddress.Parse("192.168.1.2");
IPEndPoint ipep = new IPEndPoint(myIP,8888);
try
{
s.Connect(ipep);
}
catch (SocketException ex)
{
MessageBox.Show("connect error: " + ex.Message);
return;
}
//如果在执行Socket连接时,服务器的Socket侦听没有开启的话,会产生一个SocketException异常,如果没有异常发生,那恭喜你,你已经与服务器连接上了,接下来就可以跟服务器通信了。
3、成功连接后我们就可以通讯啦!!通过 Send/SendTo 方法向远程服务器发送数据,而后可以通过 Receive/ReceiveFrom 从服务端接收数据。
Send : public int Send(byte[] buffer); //直接把要发送的数据转换为System.Byte 类型的数组发送,返回已发送到连接的Socket 的字节数
public int Send(byte[] buffer, int offset, int size, SocketFlags socketFlags); //offset发送的开始位置,size: 要发送的字节数,SocketFlags
指定套接字接收和发送的行为;
......
Receive: public int Receive(byte[] buffer, int offset, int size, SocketFlags socketFlags); //buffer存储所接收数据的位置,所以在Receive前要先初始化 byte[], offset:buffer存储的位置,size:接收的字节数
......
通常接收方都必须绑定本机的终结点,然后侦听
IPEndPoint ipep = new IPEndPoint(IPAddress.Any, int.Parse("8888")); //IPAddress.Any指定所有网络接口上的客户端活动
//创建一个套接字
Socket rec = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//绑定套接字到指定端口
rec.Bind(ipep);
rec.Listen(10); //10是挂起连接队列的最大长度。
while (true)
{
Socket s = rec.Accept();
string SendFileName = System.Text.Encoding.Unicode.GetString(Module.ReceiveVarData(s));
//接收完后记得关闭Socket
s.Close();
......
}
进入while循环,等待新的联接;如果有新的联接,那么建立新的socket来对应这个联接的会话。值得注意的就是这一句联接代码:rec.Accept()。执行这一句的时候,程序就在这个地方等待,直到有新的联检请求的时候程序才会执行下一句。这是同步执行,当然也可以异步执行。
下面两个是常用的socket发送接收函数:
public static int SendVarData(Socket s, byte[] data)
{
int total = 0;
int size = data.Length;
int dataleft = size;
int sent;
byte[] datasize = new byte[4];
datasize = BitConverter.GetBytes(size);
sent = s.Send(datasize);
while (total < size)
{
sent = s.Send(data, total, dataleft, SocketFlags.None);
total += sent;
dataleft -= sent;
}
return total;
}
//接收函数
public static byte[] ReceiveVarData(Socket s)
{
int total = 0;
int recv;
byte[] datasize = new byte[4];
recv = s.Receive(datasize, 0, 4, SocketFlags.None);
int size = BitConverter.ToInt32(datasize, 0);
int dataleft = size;
byte[] data = new byte[size];
while (total < size)
{
recv = s.Receive(data, total, dataleft, SocketFlags.None);
if (recv == 0)
{
data = null;
break;
}
total += recv;
dataleft -= recv;
}
return data;
}
posted on 2011-07-02 10:53 congplayer 阅读(3983) 评论(6) 编辑 收藏 举报