命名空间:

  在网络环境下,我们最感兴趣的两个命名空间是System.Net和 System.Net.Sockets。

  System.Net命名空间通常与较高程的操作有关,例如download或upload,试用HTTP和其他协议进行Web请求等等

  System.Net.Sockets命名空间所包含的类通常与较低程的操作有关。如果要直接使用Sockets或者 TCP/IP之类的协议

Socket对象创建:

  针对Socket编程,.NET 框架的 Socket 类是 Winsock32 API 提供的套接字服务的托管代码版本。Socket可以象流Stream一样被视为一个数据通道,这个通道架设在应用程序端(客户端)和远程服务器端之间,而后,数据的读取(接收)和写入(发送)均针对这个通道来进行。

  Socket 类支持两种基本模式:同步和异步。其区别在于:在同步模式中,对执行网络操作的函数(如 Send 和 Receive)的调用一直等到操作完成后才将控制返回给调用程序。在异步模式中,这些调用立即返回。

  在使用之前,你需要首先创建Socket对象的实例,这可以通过Socket类的构造方法来实现:

  public Socket(AddressFamily addressFamily,SocketType socketType,ProtocolType protocolType);

  其中,addressFamily 参数指定 Socket 使用的寻址方案,socketType 参数指定 Socket 的类型,protocolType 参数指定 Socket 使用的协议。

  下面的示例语句创建一个 Socket,它可用于在基于 TCP/IP 的网络(如 Internet)上通讯。

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

  若要使用 UDP 而不是 TCP,需要更改协议类型,如下面的示例所示:

Socket temp = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);

一旦创建 Socket,在客户端,你将可以通过Connect方法连接到指定的服务器,并通过Send/SendTo

Socket操作流程:

  方法向远程服务器发送数据,而后可以通过 Receive/ReceiveFrom从服务端接收数据;而在服务器端,你需要使用Bind方法绑定所指定的接口使Socket与一个本地终结点相联,并通过Listen方法侦听该接口上的请求,当侦听到用户端的连接时,调用Accept完成连接的操作,创建新的Socket以处理传入的连接请求。使用完 Socket 后,记住使用 Shutdown 方法禁用 Socket,并使用 Close 方法关闭 Socket。

终结点:

  在Internet中,TCP/IP 使用套接字(一个网络地址和一个服务端口号)来唯一标识设备。网络地址(IP)标识网络上的特定设备;端口号(Port)标识要连接到的该设备上的特定服务。网络地址和服务端口的组合称为终结点,在 .NET 框架中正是由 EndPoint 类表示这个终结点,它提供表示网络资源或服务的抽象,用以标志网络地址等信息。

  .Net同时也为每个受支持的地址族定义了 EndPoint 的子代;对于 IP 地址族,该类为 IPEndPoint。IPEndPoint 类包含应用程序连接到主机上的服务所需的主机和端口信息。

IP地址获取方式:

  用到IPEndPoint类的时候就不可避免地涉及到计算机IP地址,System.Net命名空间中有两种类可以得到IP地址实例:

  IPAddress类: 在同一局域网中采用的获取方式。 IPAddress 类包含计算机在 IP 网络上的地址。其Parse方法可将 IP 地址字符串转换为 IPAddress 实例。下面的语句创建一个 IPAddress 实例:

IPAddress myIP = IPAddress.Parse("192.168.0.1");

  Dns 类:  在互联网中采用的获取方式。 向使用 TCP/IP Internet 服务的应用程序提供域名服务。其Resolve 方法查询 DNS 服务器以将用户友好的域名(如"host.mydomain.com")映射到数字形式的 Internet 地址(如 192.168.0.1)。

  Resolve方法 返回一个 IPHostEnty 实例,该实例包含所请求名称的地址和别名的列表。大多数情况下,可以使用 AddressList 数组中返回的第一个地址。下面的代码获取一个 IPAddress 实例,该实例包含服务器 host.mydomain.com 的 IP 地址。

  IPHostEntry ipHostInfo = Dns.Resolve("host.mydomain.com ");

  IPAddress ipAddress = ipHostInfo.AddressList[0];

  你也可以使用GetHostName方法得到IPHostEntry实例:

  IPHosntEntry hostInfo=Dns.GetHostByName("host.mydomain.com ")

  在使用以上方法时,你将可能需要处理以下几种异常:

  SocketException异常:访问Socket时操作系统发生错误引发

  ArgumentNullException异常:参数为空引用引发

  ObjectDisposedException异常:Socket已经关闭引发

通信过程示例:

服务器端:

服务器端接收客户端数据步骤:

  1. 创建一个服务器端的实体
  2. 创建服务器端对客户端的监听
  3. EndAccept方法返回客户端实体
  4. 新建线程负责接收客户端的数据
 public class CM
{
public static bool ISAddSocekt = true;//现在是否继续接收新的客户端连接 public static int AddressIndex = ;//这是当前与服务器端连接的第几个客户端
//病历号和客户端IP关联表(key:病历号 value:客户端的IP地址,不包含port)
public static Dictionary<string, string> dic_Patient_IP = new Dictionary<string, string>();
//客户端IP和客户端连接顺序关联表(key:病历号 value:客户端的IP地址,不包含port)
public static Dictionary<string, int> dic_IP_Index = new Dictionary<string, int>();
//客户端集合 key:客户端IP地址,Value:客户端实体
public static Dictionary<string, Socket> dic_IP_Socket = new Dictionary<string, Socket>(); private delegate void AcceptDelegete();
private delegate void ReadDelegete(Socket s); public static int ServerPort = ;//服务器端端口
public static Socket serverSocket;//服务器端
//用20个线程分别接受一个设备的数据
public static int ClientCount_Max = ;//客户端的最大数量 public static void Listen()
{
AcceptDelegete listen = AcceptConnection;
IAsyncResult asy = listen.BeginInvoke(null, null);
}
private static void AcceptConnection()
{
try
{
serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPEndPoint localEP = new IPEndPoint(IPAddress.Any, ServerPort);
//将socket绑定到本地的终结点上
serverSocket.Bind(localEP);
//开始监听
serverSocket.Listen(ClientCount_Max);
serverSocket.BeginAccept(new AsyncCallback(AcceptCallBack), null); }
catch (Exception ex)
{ }
} private static void AcceptCallBack(IAsyncResult iar)
{
try
{
while (ISAddSocekt)
{
// 调用EndAccept完成BeginAccept异步调用,返回一个新的Socket处理与客户的通信
Socket clientSocket = serverSocket.EndAccept(iar);
IPEndPoint clientPoint = clientSocket.RemoteEndPoint as IPEndPoint; if (!dic_IP_Index.ContainsKey(clientPoint.Address.ToString()))
{
dic_IP_Index.Add(clientPoint.Address.ToString(), AddressIndex);
AddressIndex += ;
//去除旧的客户端实体
dic_IP_Socket.Remove(clientPoint.Address.ToString());
}
dic_IP_Socket.Add(clientPoint.Address.ToString(), clientSocket); //开启新线程读取数据
CM_Data client = new CM_Data(clientSocket);
Thread thClient = new Thread(new ThreadStart(client.ClientServer));
thClient.Start();
//在达到多大的客户端连接限制前,继续监听是否有新的客户端连接
if (dic_IP_Index.Count < ClientCount_Max)
{
serverSocket.BeginAccept(new AsyncCallback(AcceptCallBack), null);
}
}
}
catch (Exception ex)
{ }
}
} //在新线程中不同的循环接收客户端发送过来的数据信息
// CM_Data类里的代码
public class CM_Data
{
Encoding encoding = Encoding.GetEncoding("GB2312"); //解码器(可以用于汉字)
private Socket client;//当前与服务器端通信的客户端实体 private byte[] receiveBytes = new byte[];//服务器端设置缓冲区
private int recCount;
byte[] byte_Data;
//传递连接socket
public CM_Data(Socket ClientSocket)
{
this.client = ClientSocket;
} public void ClientServer()
{ try
{
while (true)
{
recCount = client.Receive(receiveBytes, receiveBytes.Length, );//从客户端接收信息,recCount为有效数据的个数
if (recCount != )//当服务器端的缓冲区接收到的信息不为空时
{
byte_Data = new byte[recCount];
for (int i = ; i < recCount; i++)
{
byte_Data[i] = receiveBytes[i];
}
//获取数据后的数据处理
DataRead(byte_Data); }
else
{
break;
}
}
}
catch (Exception ex)
{
MessageBox.Show("数据接收时发生错误:"+ex.Message);
}
client.Close();
}

服务器端接收客户端数据

服务器端向客户端发送数据:

  1. 获取当前与服务器端通信的客户端(或者要与之通信的目标客户端)
  2. BeginSend 将数据发送,要发送的数据使用的是byte数组的形式。
  3. 示例中向客户端发送的数据也是异步发送的
public void WorkCommand(string clientIP,int WorkState)
{
Socket client = (Socket)CM.dic_IP_Socket[clientIP]; byte[] b1 = new byte[];
b1[] = 0x55;
b1[] = 0xaa;
b1[] = 0x04;
b1[] = 0x81;
switch (WorkState)
{
case : b1[] = 0x01; break;
case : b1[] = 0x02; break;
case : b1[] = 0x03; break;
case : b1[] = 0x04; break;
}
b1[] = CM_Data.GetParityBit(b1) ;
client.BeginSend(b1, , b1.Length, SocketFlags.None, new AsyncCallback(SendCallBack), client);
} private void SendCallBack(IAsyncResult iar)
{
Socket workerSocket = (Socket)iar.AsyncState;
workerSocket.EndSend(iar);
}

服务器端向客户端发送数据

客户端:

  项目的客户端代码是否下位机完成的(使用C++代码),下面的客户端示例,是我在测试程序中使用到的c#版本的代码示例。

客户端接收服务器端数据步骤:

  1. 创建客户端实体,IPEndPoint 里指定的是服务器端的IP地址和服务器端的端口号。
  2. 客户端等待服务器端的连接。
  3. 客户端循环等待服务器端的发送数据
private int serverPort = ;
public byte[] dataBuffer = new byte[];
Socket client; //连接服务器
private void ServerConnection()
{
try
{
client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPAddress ip = IPAddress.Parse("192.168.10.188");
IPEndPoint iep = new IPEndPoint(ip, );
client.BeginConnect(iep, new AsyncCallback(Connect), null);
}
catch { }
} private void Connect(IAsyncResult asy)
{ try
{
client.EndConnect(asy);
client.BeginReceive(dataBuffer, , dataBuffer.Length, SocketFlags.None, new AsyncCallback(RecieveCallBack), null);
}
catch { }
} //接收byte字节方式
private void RecieveCallBack(IAsyncResult iar)
{
try
{
int iRx = client.EndReceive(iar); byte[] byte_Receive = new byte[iRx];
for (int i = ; i < iRx; i++)
{
byte_Receive[i] = dataBuffer[i];
listBox1.Items.Add(Convert.ToString(byte_Receive[i], ));
}
string revStr = System.Text.Encoding.UTF7.GetString(byte_Receive, , iRx); //继续监听下一次的数据接收
client.BeginReceive(dataBuffer, , dataBuffer.Length, SocketFlags.None, new AsyncCallback(RecieveCallBack), null); }
catch { }
}

客户端接收服务器端数据

Void SendMessage()
{
try
{
byte[] buffer = System.Text.Encoding.Default.GetBytes(textBox1.Text);
int snLen = ;
client.BeginSend(buffer, snLen, buffer.Length, SocketFlags.None, new AsyncCallback(SendCallBack), client);
}
catch { }
}

客户端向服务器端发送数据

c#实现Socket网络编程的更多相关文章

  1. Linux Socket 网络编程

    Linux下的网络编程指的是socket套接字编程,入门比较简单.在学校里学过一些皮毛,平时就是自学玩,没有见识过真正的socket编程大程序,比较遗憾.总感觉每次看的时候都有收获,但是每次看完了之后 ...

  2. Python Socket 网络编程

    Socket 是进程间通信的一种方式,它与其他进程间通信的一个主要不同是:它能实现不同主机间的进程间通信,我们网络上各种各样的服务大多都是基于 Socket 来完成通信的,例如我们每天浏览网页.QQ ...

  3. Python全栈【Socket网络编程】

    Python全栈[socket网络编程] 本章内容: Socket 基于TCP的套接字 基于UDP的套接字 TCP粘包 SocketServer 模块(ThreadingTCPServer源码剖析) ...

  4. python之Socket网络编程

    什么是网络? 网络是由节点和连线构成,表示诸多对象及其相互联系.在数学上,网络是一种图,一般认为专指加权图.网络除了数学定义外,还有具体的物理含义,即网络是从某种相同类型的实际问题中抽象出来的模型.在 ...

  5. Python之路【第七篇】python基础 之socket网络编程

    本篇文章大部分借鉴 http://www.cnblogs.com/nulige/p/6235531.html python socket  网络编程 一.服务端和客户端 BS架构 (腾讯通软件:ser ...

  6. Socket网络编程-基础篇

    Socket网络编程 网络通讯三要素: IP地址[主机名] 网络中设备的标识 本地回环地址:127.0.0.1 主机名:localhost 端口号 用于标识进程的逻辑地址 有效端口:0~65535 其 ...

  7. Socket网络编程--FTP客户端

    Socket网络编程--FTP客户端(1)(Windows) 已经好久没有写过博客进行分享了.具体原因,在以后说. 这几天在了解FTP协议,准备任务是写一个FTP客户端程序.直接上干货了. 0.了解F ...

  8. windows下的socket网络编程

    windows下的socket网络编程 windows下的socket网络编程 clinet.c 客户端 server.c 服务器端 UDP通信的实现 代码如下 已经很久没有在windows下编程了, ...

  9. windows下的socket网络编程(入门级)

    windows下的socket网络编程 clinet.c 客户端 server.c 服务器端 UDP通信的实现 代码如下 已经很久没有在windows下编程了,这次因为需要做一个跨平台的网络程序,就先 ...

  10. Java Socket 网络编程心跳设计概念

    Java Socket 网络编程心跳设计概念   1.一般是用来判断对方(设备,进程或其它网元)是否正常动行,一 般采用定时发送简单的通讯包,如果在指定时间段内未收到对方响应,则判断对方已经当掉.用于 ...

随机推荐

  1. STM32F0xx_EXIT中断配置详细过程

    Ⅰ.概述 EXIT外部中断在使用到按键或者开关控制等应用中比较常见,低功耗中断唤醒也是很常见的一种.因此,EXIT在实际项目开发中也是比较常见的一种. STM32F0中外部中断EXIT属于中断和事件的 ...

  2. 13.python中的字典

    字典其实和之前的元祖和列表功能相似,都是用来储存一系列对象的.也就是一种可变容器,或者是我所比喻的革新派的菜单. 但也不是完全相同,我在之前曾经将字典称为特殊的'序列',是字典拥有序列的部分特性,但是 ...

  3. Python脚本控制的WebDriver 常用操作 <四> 设置浏览器大小

    下面将使用webdriver来控制浏览器窗口的大小 测试用例场景 设置浏览器窗口的大小有下面两个比较常见的用途: 在统一的浏览器大小下运行用例,可以比较容易的跟一些基于图像比对的工具进行结合,提升测试 ...

  4. R语言的字符串处理

    R语言字符串的拼接 content<-paste("124235","789","124",sep="@") 运行 ...

  5. MIFARE系列3《卡能源和数据传递》

    在MIFARE卡中,能量和数据通过天线传输,卡中天线为几匝线圈,直接连接到芯片上,不再需要额外的组件.线圈嵌入塑料中,形成了一个无源的非接触卡. 读卡器向IC发一组固定频率的电磁波,卡内有一个IC串联 ...

  6. windows32位下安装mongodb

    下载mongodb:http://downloads.mongodb.org/win32/mongodb-win32-i386-2.4.5.zip 给mongodb指定一个数据存放路径:这里我们放在m ...

  7. eclipse+cdt+minGW (C/C++ 编译)

    1. 安装Eclipse CDT 方法1: 已安装Eclipse的话,可以通过菜单Help->Install New Software,安装CDT插件. 点击ADD后 Name:CDT    L ...

  8. iOS中MVC设计模式

    在组织大型项目的代码文件时,我们常用MVC的思想.MVC的概念讲起来非常简单,就和对象(object)一样.但是理解和应用起来却非常困难.今天我们就简单总结一下MVC设计理念. MVC(Model V ...

  9. C语言函数返回数组

    #include "stdio.h"/*int* set(int a,int *c){ int *b; b=malloc(sizeof(int)*3); c[0]=a; c[1]= ...

  10. oracle odbc配置

    oracle odbc配置 Win7 64位 下安装oracle odbc 不能使用控制面板中 “管理工具”->“数据源(OBDC)”中安装数据源. 而要在“ 运行” 中输入  C:\Windo ...