完整使用socket进行通信程序设计Word文档下载推荐.docx
《完整使用socket进行通信程序设计Word文档下载推荐.docx》由会员分享,可在线阅读,更多相关《完整使用socket进行通信程序设计Word文档下载推荐.docx(50页珍藏版)》请在冰豆网上搜索。
③接收到重复服务请求,处理该请求并发送应答信号;
④返回第二步,等待另一客户请求;
⑤关闭服务器。
客户方:
1打开一个通信通道,并连接到服务器所在主机的特定端口;
②向服务器发送服务请求报文,等待并接收应答;
继续提出请求……
③请求结束后关闭通信通道并终止.
2、套接字
套接字是通信的基石,是支持TCP/IP协议的网络通信的基本操作单元。
可以将套接字看作不同主机间的进程进行双向通信的端点,它构成了单个主机内及整个网络间的编程界面。
套接字存在于通信域中,通信域是为了处理一般的线程通过套接字通信而引进的一种抽象概念。
套接字通常和同一个域中的套接字交换数据(数据交换也可能穿越域的界限,但这时一定要执行某种解释程序)。
各种进程使用这个相同的域互相之间用Internet协议簇来进行通信.
套接字可以根据通信性质分类,这种性质对于用户是可见的。
应用程序一般仅在同一类的套接字间进行通信。
不过只要底层的通信协议允许,不同类型的套接字间也照样可以通信。
套接字有两种不同的类型:
流套接字和数据报套接字。
套接字工作原理:
要通过互联网进行通信,你至少需要一对套接字,其中一个运行于客户机端,我们称之为ClientSocket,另一个运行于服务器端,我们称之为ServerSocket。
根据连接启动的方式以及本地套接字要连接的目标,套接字之间的连接过程可以分为三个步骤:
服务器监听,客户端请求,连接确认。
所谓服务器监听,是服务器端套接字并不定位具体的客户端套接字,而是处于等待连接的状态,实时监控网络状态.
所谓客户端请求,是指由客户端的套接字提出连接请求,要连接的目标是服务器端的套接字。
为此,客户端的套接字必须首先描述它要连接的服务器的套接字,指出服务器端套接字的地址和端口号,然后就向服务器端套接字提出连接请求。
所谓连接确认,是指当服务器端套接字监听到或者说接收到客户端套接字的连接请求,它就响应客户端套接字的请求,建立一个新的线程,把服务器端套接字的描述发给客户端,一旦客户端确认了此描述,连接就建立好了。
而服务器端套接字继续处于监听状态,继续接收其他客户端套接字的连接请求。
3、C#Socket
在C#中提供了两种网络服务,一种是Socket类,另一种是TcpListener(服务器),TcpClient(客户端);
Socket类为网络通信提供了一套丰富的方法和属性.Socket类允许您使用ProtocolType枚举中所列出的任何一种协议执行异步和同步数据传输.
Microsoft.NetFramework为应用程序访问Internet提供了分层的、可扩展的以及受管辖的网络服务,其名字空间System.Net和System。
Net.Sockets包含丰富的类可以开发多种网络应用程序。
.Net类采用的分层结构允许应用程序在不同的控制级别上访问网络,开发人员可以根据需要选择针对不同的级别编制程序,这些级别几乎囊括了Internet的所有需要--从socket套接字到普通的请求/响应,更重要的是,这种分层是可以扩展的,能够适应Internet不断扩展的需要。
抛开ISO/OSI模型的7层构架,单从TCP/IP模型上的逻辑层面上看,.Net类可以视为包含3个层次:
请求/响应层、应用协议层、传输层。
WebReqeust和WebResponse代表了请求/响应层,支持Http、Tcp和Udp的类组成了应用协议层,而Socket类处于传输层。
传输层位于这个结构的最底层,当其上面的应用协议层和请求/响应层不能满足应用程序的特殊需要时,就需要使用这一层进行Socket套接字编程。
而在。
Net中,System。
Net.Sockets命名空间为需要严密控制网络访问的开发人员提供了WindowsSockets(Winsock)接口的托管实现。
System。
Net命名空间中的所有其他网络访问类都建立在该套接字Socket实现之上,如TCPClient、TCPListener和UDPClient类封装有关创建到Internet的TCP和UDP连接的详细信息;
NetworkStream类则提供用于网络访问的基础数据流等,常见的许多Internet服务都可以见到Socket的踪影,如Telnet、Http、Email、Echo等,这些服务尽管通讯协议Protocol的定义不同,但是其基础的传输都是采用的Socket。
其实,Socket可以象流Stream一样被视为一个数据通道,这个通道架设在应用程序端(客户端)和远程服务器端之间,而后,数据的读取(接收)和写入(发送)均针对这个通道来进行。
可见,在应用程序端或者服务器端创建了Socket对象之后,就可以使用Send/SentTo方法将数据发送到连接的Socket,或者使用Receive/ReceiveFrom方法接收来自连接Socket的数据;
针对Socket编程,.NET框架的Socket类是Winsock32API提供的套接字服务的托管代码版本。
其中为实现网络编程提供了大量的方法,大多数情况下,Socket类方法只是将数据封送到它们的本机Win32副本中并处理任何必要的安全检查。
使用socket其间用到的方法/函数有:
Socket.Connect方法:
建立到远程设备的连接
publicvoidConnect(EndPointremoteEP)(有重载方法)
Socket.Send方法:
从数据中的指示位置开始将数据发送到连接的Socket。
publicintSend(byte[],int,SocketFlags);
(有重载方法)
Socket.SendTo方法将数据发送到特定终结点。
publicintSendTo(byte[],EndPoint);
Socket。
Receive方法:
将数据从连接的Socket接收到接收缓冲区的特定位置.
publicintReceive(byte[],int,SocketFlags);
Socket.ReceiveFrom方法:
接收数据缓冲区中特定位置的数据并存储终结点.
publicintReceiveFrom(byte[],int,SocketFlags,refEndPoint);
Socket.Bind方法:
使Socket与一个本地终结点相关联:
publicvoidBind(EndPointlocalEP);
Socket.Listen方法:
将Socket置于侦听状态。
publicvoidListen(intbacklog);
Accept方法:
创建新的Socket以处理传入的连接请求。
publicSocketAccept();
Socket.Shutdown方法:
禁用某Socket上的发送和接收
publicvoidShutdown(SocketShutdownhow);
Close方法:
强制Socket连接关闭
publicvoidClose();
TcpClient类基于Socket类构建,这是它能够以更高的抽象程度提供TCP服务的基础。
因此许多应用层上的通讯协议,比如FTP(FileTransfersProtocol)文件传输协议、HTTP(HypertextTransfersProtocol)超文本传输协议等都直接创建在TcpClient等类之上.
TcpClient类,TcpListener类提供了一些简单的方法,用于在各模式下通过网络来连接、发送和接收流数据。
为使TcpClient连接并交换数据,使用
TCPProtocolType创建的TcpListener或Socket必须侦听是否有传入的连接请求。
可以使用下面两种方法之一连接到该侦听器:
(1)创建一个TcpClient,并调用三个可用的Connect方法之一.
(2)使用远程主机的主机名和端口号创建TcpClient。
此构造函数将自动尝试一个连接。
TcpClient和TcpListener使用NetworkStream类表示网络。
使用GetStream方法返回网络流,然后调用该流的Read和Write方法.NetworkStream不拥有协议类的基础套接字,因此关闭它并不影响套接字.
TCPClient类使用TCP从Internet资源请求数据.TCP协议建立与远程终结点的连接,然后使用此连接发送和接收数据包。
TCP负责确保将数据包发送到终结点并在数据包到达时以正确的顺序对其进行组合.
从名字上就可以看出,TcpClient类专为客户端设计,它为TCP网络服务提供客户端连接。
TcpClient提供了通过网络连接、发送和接收数据的简单方法。
基于以上,本次实验中我使用了TcpClient类和TcpListener。
主要数据结构:
主程序分成两部分,在服务器端由于要实现多用户通信,所以建立一个Client类用于存放各个连接服务器端客户的信息.该类的主要结构如下:
classClient
{
publicTcpClientclient{get;
privateset;
}
publicBinaryReaderbr{get;
}
publicBinaryWriterbw{get;
privateset;
publicstringclientName{get;
set;
publicClient(TcpClientclient){}
publicvoidClose(){}
}
其余程序部分没有特别需要说明的数据结构,都是有关于socket通信的,在上面部分已经详述,在这里不作赘述。
主要程序流程:
服务器和客户端之间面向连接的基于套接字的系统调用时序图如下图所示
图1Socket通信流程图
程序设计:
(一)服务端设计
1、利用VS2012应用程序向导生成C#程序框架.
2、设计界面如下:
设置属性如下:
namespacechatserver
{
partialclassFServer
///<
summary〉
///Requireddesignervariable.
///〈/summary〉
privateSystem.ComponentModel。
IContainercomponents=null;
summary>
///Cleanupanyresourcesbeingused。
///〈paramname="
disposing”>
trueifmanagedresourcesshouldbedisposed;
otherwise,false.<
/param>
protectedoverridevoidDispose(booldisposing)
if(disposing&
&(components!
=null))
{
components.Dispose();
base。
Dispose(disposing);
#regionWindowsFormDesignergeneratedcode
///〈summary>
///RequiredmethodforDesignersupport-donotmodify
///thecontentsofthismethodwiththecodeeditor。
/summary>
privatevoidInitializeComponent()
this.label1=newSystem。
Windows。
Forms.Label();
this。
txtIPInfo=newSystem。
Windows.Forms。
TextBox();
label2=newSystem.Windows.Forms.Label();
txtPortInfo=newSystem.Windows.Forms.TextBox();
this.btnServerStart=newSystem.Windows.Forms.Button();
this.label3=newSystem。
Forms。
Label();
richTxtMessage=newSystem.Windows。
Forms.RichTextBox();
btnStopServer=newSystem。
Forms.Button();
label4=newSystem。
Windows.Forms.Label();
this.richTxtOnlineUser=newSystem.Windows。
SuspendLayout();
//
//label1
label1.AutoSize=true;
label1.Location=newSystem。
Drawing.Point(33,24);
this.label1.Name=”label1"
;
this.label1。
Size=newSystem。
Drawing.Size(41,12);
label1.TabIndex=0;
Text="
IP地址"
//txtIPInfo
txtIPInfo.Location=newSystem.Drawing.Point(80,21);
txtIPInfo。
Name=”txtIPInfo"
;
this.txtIPInfo。
Drawing.Size(94,21);
TabIndex=1;
Text=”127。
0。
0.1”;
//label2
label2。
AutoSize=true;
label2.Location=newSystem.Drawing.Point(219,24);
label2.Name=”label2"
label2.Size=newSystem.Drawing.Size(95,12);
label2.TabIndex=2;
this.label2.Text="
端口号(0—65535)"
//txtPortInfo
txtPortInfo。
Location=newSystem。
Drawing.Point(320,20);
this.txtPortInfo.Name="
txtPortInfo"
this.txtPortInfo。
Size=newSystem.Drawing.Size(79,21);
txtPortInfo.TabIndex=3;
1”;
//btnServerStart
this.btnServerStart。
Drawing。
Point(433,17);
this.btnServerStart.Name=”btnServerStart"
RightToLeft=System。
RightToLeft。
No;
btnServerStart.Size=newSystem。
Size(80,25);
TabIndex=4;
btnServerStart.Text="
启动服务器"
this.btnServerStart.UseVisualStyleBackColor=true;
btnServerStart.Click+=newSystem。
EventHandler(this.btnServerStart_Click);
//label3
this.label3.AutoSize=true;
label3。
Point(219,64);
label3.Name="
label3"
Size=newSystem.Drawing。
Size(53,12);
this.label3.TabIndex=5;
Text=”聊天内容”;
//richTxtMessage
richTxtMessage.Location=newSystem.Drawing.Point(221,89);
this.richTxtMessage.Name="
richTxtMessage"
richTxtMessage。
Size(397,303);
this.richTxtMessage。
TabIndex=6;
Text=”"
//btnStopServer
btnStopServer.FlatStyle=System.Windows.Forms。
FlatStyle。
System;
btnStopServer.Location=newSystem.Drawing。
Point(543,17);
this.btnStopServer。
Name="
btnStopServer"
btnStopServer.Size=newSystem。
Size(80,25);
btnStopServer。
TabIndex=10;
btnStopServer.Text="
停止服务器"
UseVisualStyleBackColor=true;
this.btnStopServer.Click+=newSystem。
EventHandler(this。
btnStopServer_Click);
//label4
this.label4.AutoSize=true;
this.label4。
Location=newSystem.Drawing.Point(26,64);
label4.Name=”label4"
this.label4.Size=newSystem。
Drawing.Size(77,12);
this.label4.TabIndex=11;
label4.Text="
当前在线用户”;
//richTxtOnlineUser
richTxtOnlineUser。
Point(28,89);
richTxtOnlineUser.Name="
richTxtOnlineUser"
this.richTxtOnlineUser。
Size(146,303);
TabIndex=12;
this.richTxtOnlineUser.Text="
”;
//FServer
AutoScaleDimensions=newSystem.Drawing.SizeF(6F,12F);
AutoScaleMode=System。
Windows.Forms.AutoScaleMode。
Font;
this.ClientSize=newSystem.Drawing.Size(648,418);
Controls.Add(this。
richTxtOnlineUser);
this.Controls.Add(this。
label4);
btnStopServer);
Controls。
Add(this。
ri