C#语言中的SOCKET

C#语言中的SOCKET  所谓Socket通常也称作“套接字”,应用 程序通常通过“套接字”向网络发出请求或者应答网络请求。根据连接启动的方式以及本地套接字要连接的目标,套接字之间的连接过程可以分为三个步骤:服务器监听, 客户端请求,连接确认。
  服务器监听:是服务器端套接字并不定位具体的客户端套接字,而是处于等待连接的状态,实时监控网络状态。
  客户端请求:是指由客户端的套接字提出连接请求,要连接的目标是服务器端的套接字。为此,客户端的套接字必须首先描述它要连接的服务器的套接字,指出服务器端套接字的地址和端口号,然后就向服务器端套接字提出连接请求。
  连接确认:是指当服务器端套接字监听到或者说接收到客户端套接字的连接请求,它就响应客户端套接字的请求,建立一个新的线程,把服务器端套接字的描述发给客户端,一旦客户端确认了此描述,连接就建立好了。而服务器端套接字继续处于监听状态,继续接收其他客户端套接字的连接请求。
  Socket通信以其传输速度快且稳定的优点在程序开发中应用非常的广泛,下面的范例就简要的介绍了Socket在C#中应用。
  public class XmlSocket
  {
  //异步socket诊听
  // Incoming data from client.从客户端传来的数据
  public static string data = null;
  // Thread signal.线程 用一个指示是否将初始状态设置为终止的布尔值初始化 ManualResetEvent 类的新实例。
  public static ManualResetEvent allDone = new ManualResetEvent(false);
  //static void Main(string[] args)
  //{
  // StartListening();
  //}
  public static void StartListening()
  {
  // Data buffer for incoming data. 传入数据缓冲
  byte[] bytes = new Byte[1024];
  // Establish the local endpoint for the socket. 建立本地端口
  // The DNS name of the computer
  // running the listener is “*******”.
  IPAddress ipAddress;
  String ipString = ConfigurationManager.AppSettings.Get(“SocketIP”);
  if (ipString==null || ipString ==String.Empty) { IPHostEntry ipHostInfo = Dns.GetHostEntry(Dns.GetHostName());
  ipAddress = ipHostInfo.AddressList[0];
  }
  else
  {
  ipAddress = IPAddress.Parse(ipString);
  }
  int port;
  String portString = ConfigurationManager.AppSettings.Get(“SocketPort”);
  if (portString==null || portString==String.Empty)
  {
  port = 11001;
  }
  else
  {
  port = int.Parse(portString);
  }
  IPEndPoint localEndPoint = new IPEndPoint(ipAddress,port);
  // Create a TCP/IP socket.
  Socket listener = new Socket(AddressFamily.InterNetwork,
  SocketType.Stream,ProtocolType.Tcp);
  // Bind the socket to the local endpoint and listen for incoming connections.绑定端口和数据
  try
  {
  listener.Bind(localEndPoint);
  listener.Listen(100);
  while (true)
  {
  // Set the event to nonsignaled state.设置无信号状态的事件
  allDone.Reset();
  // Start an asynchronous socket to listen for connections.重新 启动异步连接
  listener.BeginAccept(new AsyncCallback(AcceptCallback),listener);
  // Wait until a connection is made before continuing.等待连接创建后继续
  allDone.WaitOne();
  }
  }
  catch (Exception e)
  {
  //
  }
  }
  public static void AcceptCallback(IAsyncResult ar)
  {
  try
  {
  // Signal the main thread to continue.接受回调方法 该方法的此节向主应用程序线程发出信号,
  //让它继续处理并建立与客户端的连接
  allDone.Set();
  // Get the socket that handles the client request.获取客户端请求句柄
  Socket listener = (Socket)ar.AsyncState;
  Socket handler = listener.EndAccept(ar);
  // Create the state object.
  StateObject state = new StateObject();
  state.workSocket = handler;
  handler.BeginReceive(state.buffer,0,StateObject.BufferSize,0,
  new AsyncCallback(ReadCallback),state);
  }
  catch (Exception e)
  {
  //
  }
  }
  /// <summary>
  /// 与接受回调方法一样,读取回调方法也是一个 AsyncCallback 委托。
  /// 该方法将来自客户端套接字的一个或多个字节读入数据缓冲区,然后再次调用 BeginReceive 方法,直到客户端发送的数据完成为止。
  /// 从客户端读取整个消息后,在控制台上显示字符串,并关闭处理与客户端的连接的服务器套接字。
  /// </summary>
  /// <param name=”ar”>IAsyncResult 委托</param>
  public static void ReadCallback(IAsyncResult ar)
  {
  try
  {
  String content = String.Empty;
  // Retrieve the state object and the handler socket创建自定义的状态 对象 from the asynchronous state object.
  StateObject state = (StateObject)ar.AsyncState;
  Socket handler = state.workSocket;//处理的句柄
  // Read data from the client socket. 读出
  int bytesRead = handler.EndReceive(ar);
  if (bytesRead > 0)
  {
  //业务代码
  String result = DoSomeThing(…);
  String len = Encoding.UTF8.GetBytes(result).Length.ToString().PadLeft(8,’0′);
  log.writeLine(len);
  Send(len + result,handler);
  }
  }
  catch (Exception e)
  {
  //
  }
  }
  private static void Send(String data,Socket handler)
  {
  try
  {
  // Convert the string data to byte data using UTF8 encoding.
  byte[] byteData = Encoding.UTF8.GetBytes(data);
  // Begin sending the data to the remote device.
  handler.BeginSend(byteData,0,byteData.Length,0,
  new AsyncCallback(SendCallback),handler);
  }
  catch (Exception e)
  {
  //
  }
  }
  /// <summary>
  /// 发送
  /// </summary>
  /// <param name=”ar”></param>
  private static void SendCallback(IAsyncResult ar)
  {
  try
  {
  // Retrieve the socket from the state object.
  Socket handler = (Socket)ar.AsyncState;
  // Complete sending the data to the remote device.向远端发送数据
  int bytesSent = handler.EndSend(ar);
  StateObject state = new StateObject();
  state.workSocket = handler;
  handler.BeginReceive(state.buffer,0,StateObject.BufferSize,0,new AsyncCallback(ReadCallback),state);
  handler.Shutdown(SocketShutdown.Both);
  handler.Close();
  }
  catch (Exception e)
  {
  //
  }
  }
  public static void StopListening()
  {
  allDone.Close();
  log.close();
  }
  /// <summary>
  /// 具体处理业务的方法
  /// </summary>
  /// <returns></returns>
  private static string DoSomething(int i)
  {
  //具体业务代码,返回需要返回的字符串信息
  }
  /// <summary>
  /// 写日志方法
  /// </summary>
  /// <param name=”strLog”>;写入内容</param>
  public static void WriteLog(string strLog)
  {
  //写入日志代码
  }
  }
  /// 线程执行体,转发消息
  /// </summary>
  /// <param name=”obj”>;传递给线程执行体的用户名,用以与用户通信 </param>
  private void ThreadFunc(object obj)
  {
  //通过转发表得到当前用户套接字
  Socket clientSkt = _transmit_tb[obj] as Socket;
  //主循环
  while (true)
  {
  try
  { //接受第一个数据包。
  //由于程序逻辑结构简单,所以在这里对客户机发送的第一个包内容作逐一判断,
  //这里的实现不够优雅,但不失为此简单模型的一个解决之道。
  byte[] packetBuff = new byte[_maxPacket];
  clientSkt.Receive(packetBuff);
  string _str = Encoding.Unicode.GetString(packetBuff).TrimEnd(‘\0′);
  //如果是发给不在线好友的信息
  if (_str.StartsWith(“cmd::FriendMessage”))
  {
  string UserName = _str.Substring(“cmd::FriendMessage”.Length,20).Trim();
  string MessageS = _str.Substring(“cmd::FriendMessage”.Length + 20,_str.Length - ”cmd::FriendMessage”.Length - 20);
  SaveMessage(obj as string,UserName,MessageS);
  continue;
  }
  //如果是离线请求
  if (_str.StartsWith(“cmd::RequestLogout”))
  {
  _transmit_tb.Remove(obj);
  UpdateFriendList((string)obj,false,”");
  // string svrlog = string.Format(“[系统消息]用户 {0} 在 {1} 已断开… 当前在线人数: {2}\r\n\r\n”,obj,DateTime.Now,_transmit_tb.Count);
  // Console.WriteLine(svrlog);
  //向所有客户机发送系统消息
  //foreach (DictionaryEntry de in _transmit_tb)
  //{
  // string _clientName = de.Key as string;
  // Socket _clientSkt = de.Value as Socket;
  // _clientSkt.Send(Encoding.Unicode.GetBytes(svrlog));
  //}
  Thread.CurrentThread.Abort();
  }
  //如果是请求好友列表
  if (_str.StartsWith(“cmd::RequestFriendList”))
  {
  SerializeFriendList(obj,clientSkt);
  // 将该用户不在线时的信息发送给用户
  DataTable TabMessage = ReadMessage(obj as string);
  if (TabMessage != null)
  {
  foreach (DataRow myrow in TabMessage.Rows)
  {
  if (myrow["SendUserName"].ToString() == ”System::Message”)
  {
  clientSkt.Send(Encoding.Unicode.GetBytes(myrow["Message"].ToString()));
  }
  else
  {
  clientSkt.Send(Encoding.Unicode.GetBytes(“cmd::FriendMessage” +myrow["SendUserName"].ToString().PadRight(20,’ ’) + myrow["Message"].ToString()));
  }
  }
  } //这里不需要再继续接受后继数据包了,跳出当前循环体。
  continue;
  }
  如果是请求好友列表
  //if (_str.StartsWith(“cmd::RequestOnLineList”))
  //{
  // byte[] onlineBuff = SerializeOnlineList();
  // //先发送响应信号,用户客户机的判断
  // clientSkt.Send(Encoding.Unicode.GetBytes(“cmd::RequestOnLineList”));
  // clientSkt.Send(onlineBuff);
  // //这里不需要再继续接受后继数据包了,跳出当前循环体。
  // continue;
  //} //查找用户
  if (_str.StartsWith(“Find::FindFriend”))
  {
  DataTable TabFind = TabUser.Clone();
  DataRow [] FindRow =null ;
  string UserName = _str.Substring(“Find::FindFriend”.Length,_str.Length - ”Find::FindFriend”.Length);
  if (UserName.Equals(“Find::WhoOnLine”))
  { //看谁在线
  FindRow = TabUser.Select(“ ZX = 1″);
  }
  else//精确查找
  {
  FindRow = TabUser.Select(“UserName = ‘” + UserName + ”‘”);
  }
  foreach (DataRow myrow in FindRow)
  {
  TabFind.ImportRow(myrow);
  }
  clientSkt.Send(Encoding.Unicode.GetBytes(“Find::FindFriend”));
  IFormatter format = new BinaryFormatter();
  MemoryStream stream = new MemoryStream();
  format.Serialize(stream,TabFind);
  stream.Position = 0;
  byte[] ret = new byte[_maxPacket];
  int count = 0;
  count = stream.Read(ret,0,_maxPacket);
  while (count >0)
  {
  clientSkt.Send(ret);
  count = stream.Read(ret,0,_maxPacket);
  }
  clientSkt.Send(Encoding.Unicode.GetBytes(“Find::FindFriendEnd”));
  stream.Close();
  TabFind = null;
  FindRow = null; //这里不需要再继续接受后继数据包了,跳出当前循环体。
  continue;
  } //请求添加好友
  if (_str.StartsWith(“Find::AddFriendAsk”))
  {
  string UserName = _str.Substring(“Find::AddFriendAsk”.Length,_str.Length - ”Find::AddFriendAsk”.Length);
  //通过转发表查找接收方的套接字
  if (_transmit_tb.Count != 0 && _transmit_tb.ContainsKey(UserName))
  {
  Socket receiverSkt = _transmit_tb[UserName] as Socket;
  receiverSkt.Send(Encoding.Unicode.GetBytes(“Find::AddFriendAsk” + obj as string));
  }
  //这里不需要再继续接受后继数据包了,跳出当前循环体。
  continue;
  }
  //回复答应添加好友
  if (_str.StartsWith(“Find::AddFriendYes”))
  {
  string UserName = _str.Substring(“Find::AddFriendYes”.Length,_str.Length - ”Find::AddFriendYes”.Length);
   保存数据
  DataTable TabmyFriend = new DataTable() ;
  //保存该用户
  TabmyFriend.ReadXml(MyPath + ”\\UserFriend\\” + obj as string + ”.xml”);
  DataRow newRow = TabmyFriend.NewRow();
  newRow["UserName"] = UserName;
  TabmyFriend.Rows.Add(newRow);
  TabmyFriend.WriteXml(MyPath + ”\\UserFriend\\” + obj as string + ”.xml”,XmlWriteMode.WriteSchema,false);
  //保存其好友
  TabmyFriend = new DataTable();
  TabmyFriend.ReadXml(MyPath + ”\\UserFriend\\” + UserName + ”.xml”);
  DataRow newRow1 = TabmyFriend.NewRow();
  newRow1["UserName"] = obj as string;
  TabmyFriend.Rows.Add(newRow1);
  TabmyFriend.WriteXml(MyPath + ”\\UserFriend\\” + UserName + ”.xml”,XmlWriteMode.WriteSchema,false);
  TabmyFriend = null;
  SerializeFriendList(obj,clientSkt);
  //”开始”按钮事件
  private void button1_Click(object sender,System.EventArgs e) {
  //取得预保存的文件名
  string fileName=textBox3.Text.Trim();
  //远程 主机
  string hostName=textBox1.Text.Trim();
  //端口
  int port=Int32.Parse(textBox2.Text.Trim());
  //得到主机信息
  IPHostEntry ipInfo=Dns.GetHostByName(hostName);
  //取得IPAddress[]
  IPAddress[] ipAddr=ipInfo.AddressList;
  //得到ip
  IPAddress ip=ipAddr[0];
  //组合出远程终结点
  IPEndPoint hostEP=new IPEndPoint(ip,port);
  //创建Socket 实例
  Socket socket=new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
  try
  {
  //尝试连接
  socket.Connect(hostEP);
  }
  catch(Exception se)
  {
  MessageBox.Show(“连接错误”+se.Message,”提示信息
  ,MessageBoxButtons.RetryCancel,MessageBoxIcon.Information);
  }
  //发送给远程主机的请求内容串
  string sendStr=”GET / HTTP/1.1\r\nHost: ” + hostName +
  “\r\nConnection: Close\r\n\r\n”;
  //创建bytes字节数组以转换发送串
  byte[] bytesSendStr=new byte[1024];
  //将发送内容字符串转换成字节byte数组
  bytesSendStr=Encoding.ASCII.GetBytes(sendStr);
  try
  {
  //向主机发送请求
  socket.Send(bytesSendStr,bytesSendStr.Length,0);
  }
  catch(Exception ce)
  {
  MessageBox.Show(“发送错误:”+ce.Message,”提示信息
  ,MessageBoxButtons.RetryCancel,MessageBoxIcon.Information);
  }
  //声明接收返回内容的字符串
  string recvStr=”";
  //声明字节数组,一次接收数据的长度为1024字节
  byte[] recvBytes=new byte[1024];
  //返回实际接收内容的字节数
  int bytes=0;
  //循环读取,直到接收完所有数据
  while(true)
  {
  bytes=socket.Receive(recvBytes,recvBytes.Length,0);
  //读取完成后退出循环
  if(bytes〈=0)
  break;
  //将读取的字节数转换为字符串
  recvStr+=Encoding.ASCII.GetString(recvBytes,0,bytes);
  }
  //将所读取的字符串转换为字节数组
  byte[] content=Encoding.ASCII.GetBytes(recvStr);
  try
  {
  //创建文件流对象实例
  FileStream fs=new FileStream(fileName,FileMode.OpenOrCreate,FileAccess.ReadWrite);
  //写入文件
  fs.Write(content,0,content.Length);
  }
  catch(Exception fe)
  {
  MessageBox.Show(“文件创建/写入错误:”+fe.Message,”提示信息”,MessageBoxButtons.RetryCancel,MessageBoxIcon.Information);
  }
  //禁用Socket
  socket.Shutdown(SocketShutdown.Both);
  //关闭Socket
  socket.Close();
  }
  }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值