socket分段发送大文件的方法

stning 2009-07-28 09:57:27
请大家踊跃发表一件和贴代码。大量分分送上,up的也有分。
...全文
3446 37 打赏 收藏 转发到动态 举报
写回复
用AI写文章
37 条回复
切换为时间正序
请发表友善的回复…
发表回复
lisengl 2012-08-29
  • 打赏
  • 举报
回复
刚遇到这个问题,上来看看。
fengyecsdn 2009-07-29
  • 打赏
  • 举报
回复
其实发送1K和发送100M,在传输上没区别。
就是做保障方面要考虑周全。

我做过一个组件,代码现在不在电脑里。
所以我只讲下大概思路。楼主可以自己写出来的。

1:我的传输组件,每次传送任务包最大是2M。不建议再大了,再大,既不可靠,也浪费很多效率。如果应用层要发送大于2M的数据,则要求业务层自行处理切割。并发送指令通知对方业务层对这些包的处理方式。

2:每次任务中不大于2M的包,在组件内会呗切帧,每帧从16字节到2K都可以通过设置实现。当然,每个帧都要有帧头。帧头中包括协议信息,版本,地址等,还有帧序号,包序号,分组号等。

3:接收方户设立缓存,将接收的帧按照包序号分别缓存,并按帧序号排序,等待重组。 当某包序号的全部帧都接收到以后,则将这些帧重组为包,提交给应用层。
如果某个帧接到的数据出错,或者某帧序号出现跳跃,则接收方会向发送方发送一个通知,告知对方XX包的YY帧重发。
另外根据一定的算法,检查缓存中未完成的包和帧。如在某一定时间内该包都不再有新帧到达,或者已有的帧无法连接成为包,则丢弃该包已收到的全部帧,清空缓存,并发出通知,告知对方和本地应用层,XX包传输失败,已丢弃。

4:由于我的组件设计上是可以多包并行发送,且内设多个管道。 所以实际物理传输的数据可能是混杂的,帧尺寸也不同。所以开始作的时候,出现错误数据很多。后来发现 .NET 本身的TCPCLIENT或者 NETSTREAM对象在读写的时候常出现位数错误。比如发送126个字节,接受那实际是读128个字节,丢弃2字节。 (那些例子里 收发的都是缓冲区长度,有空数据来填补这些差位。但是我这里没有空数据补充。)所以后边的包就错啦。 后来想出个办法,所有的包都用16的倍数长度, 不足的用0来补充够16的倍数。问题解决。

我建议你也做成组件化的东西。别每次项目都写一些类似的重复的东西。



zhushoudong 2009-07-28
  • 打赏
  • 举报
回复
顶楼上的 说法,我觉得还是要看业务的需求
fengyecsdn 2009-07-28
  • 打赏
  • 举报
回复
上边的代码好长好长啊。。

其实我想简单说说思路。 楼主能提这样的问题,说明楼主对TCP或者UDP的通信实现已经完全没问题了。

要传递大文件,无非就是分块,之后考虑续传。
块分的多大 要考虑三方面, 一是你网络环境(速度啊、稳定性啊) 一个是你的业务需要(频率、数量等) 再就是你的性能要求。
块越大, 并发性,灵活性就差一些。 块越小,传输效率就差一些。

业务上分块 传输上 分帧, 加序号,设缓存, 愿意的话加验证, 最好加上时间戳。
十八道胡同 2009-07-28
  • 打赏
  • 举报
回复
顶个先,
「已注销」 2009-07-28
  • 打赏
  • 举报
回复
mark
sadikaqy 2009-07-28
  • 打赏
  • 举报
回复
建议一次不要申请太大的内存,每次固定读4k(或8k),读了就写入文件流,循环利用那个缓冲区。其他的文件流和那个缓冲区可以交给系统自己管理。只要你不要一次申请太多就好了。
LQknife 2009-07-28
  • 打赏
  • 举报
回复
先说麻烦事吧 我也做过,要是单个文件还好办定义好 包头 包体 包头里边是文件信息:文件名、文件大小等等
要是文件夹就麻烦了,接收方还要创建相应的文件夹和子目录,我是没实现 ^_^
最后是异常处理,断点续传,高级点能实现暂停功能
mjp1234airen4385 2009-07-28
  • 打赏
  • 举报
回复
要做数据校验的。
把你发送的数据用crc方法校验一下,把校验码打包到数据包里,
在服务端,取得数据后,再用同样的方法校验一下,得出的校验码和传送的校验码相同则本包有效,否则从新发送。
zzxap 2009-07-28
  • 打赏
  • 举报
回复
回调方法应调用 EndReceiveFrom 方法。当应用程序调用 BeginReceiveFrom 时,系统将会使用单独的线程来执行指定的回调方法,并将在 EndReceiveFrom 上一直阻止到 Socket 读取数据或引发异常为止。如果想要在调用 BeginReceiveFrom 方法后使原始线程阻止,请使用 WaitHandle.WaitOne。当需要原始线程继续执行时,请在回调方法中调用 T:System.Threading.ManualResetEvent 的 Set 方法。有关如何编写 callback 方法的其他信息,请参见 Callback 示例。

注意
在调用 BeginReceiveFrom 之前,必须使用 Bind 方法显式地将 Socket 绑定到本地终结点,否则 BeginReceiveFrom 将会引发 SocketException。


该方法将数据读入 buffer 参数中,并捕获从其发送数据的远程主机终结点。有关如何检索此终结点的信息,请参考 EndReceiveFrom。如果打算从未知主机或多个主机异步接收无连接的数据报,则最适合使用此方法。在这些情况下,BeginReceiveFrom 将会读取本地网络缓冲区接收到的第一个排队数据报。如果您接收到的数据报大于 buffer 的大小,则 BeginReceiveFrom 方法将在 buffer 中尽可能多地填充消息内容,并引发 SocketException。如果您使用的是不可靠协议,多余的数据将会丢失。而如果当前使用的是可靠协议,则服务提供程序将保留多余的数据,而且通过使用一个足够大的缓冲区调用 BeginReceiveFrom 方法来检索这些数据。

虽然 BeginReceiveFrom 是用于无连接协议的,但您同样可以使用面向连接的协议。如果选择这样做,则必须通过调用 Connect / BeginConnect 方法来建立远程主机连接,或者调用 Accept 或 BeginAccept 方法来接受传入的连接请求。如果在建立连接或接受连接之前就调用了 BeginReceiveFrom 方法,则您将得到 SocketException。您也可以在调用 BeginReceiveFrom 方法之前,为无连接协议建立默认远程主机。在上述任何一种情况下,BeginReceiveFrom 方法都会忽略 remoteEP 参数,并且只从已连接的或默认的远程主机接收数据。

对于面向连接的套接字,BeginReceiveFrom 将读取所有可用的数据,直到达到 size 参数所指定的字节数。

若要取消挂起的 BeginReceiveFrom,请调用 Close 方法。

下面的代码示例异步接收来自远程主机的无连接数据报。

C# code
IPHostEntry lipa = Dns.Resolve("host.contoso.com");
IPEndPoint lep = new IPEndPoint(lipa.AddressList[0], 11000);

Socket s = new Socket(lep.Address.AddressFamily,
SocketType.Dgram,
ProtocolType.Udp);

IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0);
EndPoint tempRemoteEP = (EndPoint)sender;
s.Connect(sender);

try{
while(true){
allDone.Reset();
StateObject so2 = new StateObject();
so2.workSocket = s;
Console.WriteLine("Attempting to Receive data from host.contoso.com");

s.BeginReceiveFrom(so2.buffer, 0, StateObject.BUFFER_SIZE,0, ref tempRemoteEP,
new AsyncCallback(Async_Send_Receive.ReceiveFrom_Callback), so2);
allDone.WaitOne();
}
}
catch (Exception e){
Console.WriteLine(e.ToString());
}

在端口 11000 上建立 UdpClient 连接。将很短的字符串消息发送到两个单独的远程主机。Receive 方法在接收消息前阻止执行。使用传递给 Receive 的 IPEndPoint 可以显示响应主机的标识。

C# code
// This constructor arbitrarily assigns the local port number.
UdpClient udpClient = new UdpClient(11000);
try{
udpClient.Connect("www.contoso.com", 11000);

// Sends a message to the host to which you have connected.
Byte[] sendBytes = Encoding.ASCII.GetBytes("Is anybody there?");

udpClient.Send(sendBytes, sendBytes.Length);

// Sends a message to a different host using optional hostname and port parameters.
UdpClient udpClientB = new UdpClient();
udpClientB.Send(sendBytes, sendBytes.Length, "AlternateHostMachineName", 11000);

//IPEndPoint object will allow us to read datagrams sent from any source.
IPEndPoint RemoteIpEndPoint = new IPEndPoint(IPAddress.Any, 0);

// Blocks until a message returns on this socket from a remote host.
Byte[] receiveBytes = udpClient.Receive(ref RemoteIpEndPoint);
string returnData = Encoding.ASCII.GetString(receiveBytes);

// Uses the IPEndPoint object to determine which of these two hosts responded.
Console.WriteLine("This is the message you received " +
returnData.ToString());
Console.WriteLine("This message was sent from " +
RemoteIpEndPoint.Address.ToString() +
" on their port number " +
RemoteIpEndPoint.Port.ToString());

udpClient.Close();
udpClientB.Close();

}
catch (Exception e ) {
Console.WriteLine(e.ToString());
}

另外如果你想保证传输的质量的话,用TCP/IP协议吧,它的优点是可以控制传输中的质量(降低出错率),缺点是效率稍微低点。
TcpClient 类提供了一些简单的方法,用于在同步阻止模式下通过网络来连接、发送和接收流数据。

为使 TcpClient 连接并交换数据,使用 TCP ProtocolType 创建的 TcpListener 或 Socket 必须侦听是否有传入的连接请求。可以使用下面两种方法之一连接到该侦听器:

创建一个 TcpClient,并调用三个可用的 Connect 方法之一。

使用远程主机的主机名和端口号创建 TcpClient。此构造函数将自动尝试一个连接。

注意
如果要在同步阻止模式下发送无连接数据报,请使用 UdpClient 类。


给继承者的说明 要发送和接收数据,请使用 GetStream 方法来获取一个 NetworkStream。调用 NetworkStream 的 Write 和 Read 方法与远程主机之间发送和接收数据。使用 Close 方法释放与 TcpClient 关联的所有资源。

下面的代码示例建立 TcpClient 连接。

C# code
static void Connect(String server, String message)
{
try
{
// Create a TcpClient.
// Note, for this client to work you need to have a TcpServer
// connected to the same address as specified by the server, port
// combination.
Int32 port = 13000;
TcpClient client = new TcpClient(server, port);

// Translate the passed message into ASCII and store it as a Byte array.
Byte[] data = System.Text.Encoding.ASCII.GetBytes(message);

// Get a client stream for reading and writing.
// Stream stream = client.GetStream();

NetworkStream stream = client.GetStream();

// Send the message to the connected TcpServer.
stream.Write(data, 0, data.Length);

Console.WriteLine("Sent: {0}", message);

// Receive the TcpServer.response.

// Buffer to store the response bytes.
data = new Byte[256];

// String to store the response ASCII representation.
String responseData = String.Empty;

// Read the first batch of the TcpServer response bytes.
Int32 bytes = stream.Read(data, 0, data.Length);
responseData = System.Text.Encoding.ASCII.GetString(data, 0, bytes);
Console.WriteLine("Received: {0}", responseData);

// Close everything.
stream.Close();
client.Close();
}
catch (ArgumentNullException e)
{
Console.WriteLine("ArgumentNullException: {0}", e);
}
catch (SocketException e)
{
Console.WriteLine("SocketException: {0}", e);
}

Console.WriteLine("\n Press Enter to continue...");
Console.Read();
}
zzxap 2009-07-28
  • 打赏
  • 举报
回复
int port = 1234;

int port = 1234;
IPAddress ip = IPAddress.Parse("127.0.0.1");
socket = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
IPEndPoint iep = new IPEndPoint(ip,port);
//socket.Blocking = false;
socket.Bind(iep);
socket.Listen(10);
Console.WriteLine("start......");
try
{
for (int i = 0; i < 10;i++ )
{

}
}
catch
{
Console.WriteLine("异常!");
socket.Close();
}

接收端
private void Receive(Socket socket)
{
NetworkStream ns = new NetworkStream(socket);
FileStream fs = new FileStream("c:\\file.txt", FileMode.OpenOrCreate);
bool isRead = true;
while (isRead)
{
int count = ns.Read(this._receiveBuf, 0, this._receiveBuf.Length);
int datanum = 0;
datanum = BitConverter.ToInt32(this._receiveBuf, 0); //从buffer中的前4个字节读出count
if (datanum > 0) //确定每次要接受多少字节数
{
fs.Write(this._receiveBuf, 4, datanum);
}
else //如果接受字节数为0 就推出
{
isRead = false;
}
}
this.txtFile.Text = "文件传输成功";
fs.Close();
}
---------------------
发送端
private void btSend_Click(object sender, System.EventArgs e)
{
if (this._isConnect)
{
_ns = _tc.GetStream();
string path = this.txtPath.Text.Trim();
FileStream fs = new FileStream(path, FileMode.Open);
int sendCount = 0;
byte[] countbuffer = null;
byte[] clientbuffer = new byte[1004];
while (sendCount < fs.Length && _ns.CanWrite)
{
int count = fs.Read(_sendBuf, 0, _sendBuf.Length); //读出要发送的数据
countbuffer = BitConverter.GetBytes(count);
countbuffer.CopyTo(clientbuffer,0);
_sendBuf.CopyTo(clientbuffer, 4);
this._ns.Write(clientbuffer, 0, 4 + count); //写入网络流
sendCount += count;
}
countbuffer = BitConverter.GetBytes(0); //发送完文件后 发送count = 0
this._ns.Write(countbuffer, 0, countbuffer.Length); //使接收端停止
_ns.Close();
fs.Close();
}
}

你为什么不把这两种方案结合在一起呢?
首先把文件的总长度和每次发送的大小先发送出去,等接收端接受并分析,然后开始。
比如每次发送4K(这是操作系统文件管理中使用到的最小文件大小,你可以看看你系统中的任何一个文件,占用空间都是4K的整数倍),
最后一次可能会少与4K,但是接受方是可以计算出来的。
必要时,你可以使用多线程,分段发送,接收端收集后分段组合,这还要多使用一个段号码。
socket是最底层的类,传输效率最高!
对于你说的异步操作,一句话说不清楚,基本上可以用“非阻塞模型”来概括,就是调用后立马返回,不是等到操作完成后才返回!
打个比方:阻塞模型
while(isok)
{
readdata(data);//从文件读数据
send(data); //一直等到data发送完毕后才返回,其实这期间本来可以进行下一次读操作
//影响了效率。
if(读完)
isok=false;
else
isok=true;
}
非阻塞模型,可以在发送过程中进行读取操作,提高了效率。
当然,在第二次发送前,必须等待第一次发送操作完成才行,需要检测和控制!

while (sendCount < fs.Length && _ns.CanWrite)
{
int count = fs.Read(_sendBuf, 0, _sendBuf.Length); //读出要发送的数据
countbuffer = BitConverter.GetBytes(count);
countbuffer.CopyTo(clientbuffer,0);
_sendBuf.CopyTo(clientbuffer, 4);
this._ns.Write(clientbuffer, 0, 4 + count); //写入网络流
sendCount += count;
}

有点乱:你每次读取1000还是1004??不是前四个字节是长度吗?为什么从文件里读取1004个字节啊?
BeginReceiveFrom 方法启动从远程主机异步读取无连接数据报的操作。调用 BeginReceiveFrom 方法将使您能够在单独的执行线程中接收数据。

您可以创建一个实现 AsyncCallback 委托的回调方法并将它的名称传递给 BeginReceiveFrom 方法。为此,您的 state 参数至少必须包含用于通信的已连接或默认 Socket。如果您的回调需要更多信息,则可以创建一个小型类来保存 Socket 和其他必需的信息。通过 state 参数将此类的一个实例传递给 BeginReceiveFrom 方法。

回调方法应调用 EndReceiveFrom 方法。当应用程序调用 BeginReceiveFrom 时,系统将会使用单独的线程来执行指定的回调方法,并将在 EndReceiveFrom 上一直阻止到 Socket 读取数据或引发异常为止。如果想要在调用 BeginReceiveFrom 方法后使原始线程阻止,请使用 WaitHandle.WaitOne。当需要原始线程继续执行时,请在回调方法中调用 T:System.Threading.ManualResetEvent 的 Set 方法。有关如何编写 callback 方法的其他信息,请参见 Callback 示例。

注意
在调用 BeginReceiveFrom 之前,必须使用 Bind 方法显式地将 Socket 绑定到本地终结点,否则 BeginReceiveFrom 将会引发 SocketException。


该方法将数据读入 buffer 参数中,并捕获从其发送数据的远程主机终结点。有关如何检索此终结点的信息,请参考 EndReceiveFrom。如果打算从未知主机或多个主机异步接收无连接的数据报,则最适合使用此方法。在这些情况下,BeginReceiveFrom 将会读取本地网络缓冲区接收到的第一个排队数据报。如果您接收到的数据报大于 buffer 的大小,则 BeginReceiveFrom 方法将在 buffer 中尽可能多地填充消息内容,并引发 SocketException。如果您使用的是不可靠协议,多余的数据将会丢失。而如果当前使用的是可靠协议,则服务提供程序将保留多余的数据,而且通过使用一个足够大的缓冲区调用 BeginReceiveFrom 方法来检索这些数据。

虽然 BeginReceiveFrom 是用于无连接协议的,但您同样可以使用面向连接的协议。如果选择这样做,则必须通过调用 Connect / BeginConnect 方法来建立远程主机连接,或者调用 Accept 或 BeginAccept 方法来接受传入的连接请求。如果在建立连接或接受连接之前就调用了 BeginReceiveFrom 方法,则您将得到 SocketException。您也可以在调用 BeginReceiveFrom 方法之前,为无连接协议建立默认远程主机。在上述任何一种情况下,BeginReceiveFrom 方法都会忽略 remoteEP 参数,并且只从已连接的或默认的远程主机接收数据。

对于面向连接的套接字,BeginReceiveFrom 将读取所有可用的数据,直到达到 size 参数所指定的字节数。

若要取消挂起的 BeginReceiveFrom,请调用 Close 方法。

下面的代码示例异步接收来自远程主机的无连接数据报。
BeginReceiveFrom 方法启动从远程主机异步读取无连接数据报的操作。调用 BeginReceiveFrom 方法将使您能够在单独的执行线程中接收数据。

您可以创建一个实现 AsyncCallback 委托的回调方法并将它的名称传递给 BeginReceiveFrom 方法。为此,您的 state 参数至少必须包含用于通信的已连接或默认 Socket。如果您的回调需要更多信息,则可以创建一个小型类来保存 Socket 和其他必需的信息。通过 state 参数将此类的一个实例传递给 BeginReceiveFrom 方法。

  • 打赏
  • 举报
回复
怕丢包,下载完对文件做一下MD5校验就可以了。
zgke 2009-07-28
  • 打赏
  • 举报
回复
public struct FilePack
{
/// <summary>
/// 数据包大小
/// </summary>
public ushort PackSize;

/// <summary>
/// 文件GUID
/// </summary>
public byte[] FileGuid; //16

///// <summary>
///// 包数据SHA1验证 ...
///// </summary>
//public byte[] PackSHA1;

/// <summary>
/// 包总数量
/// </summary>
public ushort PackCount;

/// <summary>
/// 包号
/// </summary>
public ushort PackIndex;

/// <summary>
/// 包数据
/// </summary>
public byte[] PackData;

}

这样发啊...
stning 2009-07-28
  • 打赏
  • 举报
回复
ls的代码不完整
muyebo 2009-07-28
  • 打赏
  • 举报
回复
我自己收集的方法,没有真正用过
       private void SendFileStream(Socket socketStream, FileStream fs, byte[] byPack, string strFileName)
{
byte[] byHead = new byte[128];
byHead[0] = byPack[0];
byHead[1] = byPack[1];

byte[] byFileName = encodingGB.GetBytes(strFileName);
byHead[2] = Convert.ToByte(byFileName.Length);

byFileName.CopyTo(byHead, 3);

if (socketStream != null)
{
SocketSendMessage(socketStream, byHead);
}
else
{
MessageBox.Show("socket");
return;
}
//socketStream.Send(byHead);

byte[] byBody = new byte[PACKET_SIZE];

int nPackCount = Convert.ToInt32(byPack[0]) * Convert.ToInt32(byPack[1]);

int nCurrentPack = 0;

while (true)
{
if (socketStream != null)
{
SocketReceiveMessage(socketStream);
}


if (Convert.ToChar(byRec[0]) == 'E')
{
fs.Dispose();
fs.Close();
break;
}
else if (Convert.ToChar(byRec[0]) == 'S')
{

nCurrentPack = Convert.ToInt32(byRec[1]) * 256 + Convert.ToInt32(byRec[2]);

fs.Seek((nCurrentPack - 1) * PACKET_SIZE, SeekOrigin.Begin);

byBody = new byte[PACKET_SIZE];
if ((nCurrentPack == nPackCount) && (nLastPackSize != 0))
{
fs.Read(byBody, 0, nLastPackSize);
}
else
{
fs.Read(byBody, 0, PACKET_SIZE);

}

if (socketStream != null)
{
SocketSendMessage(socketStream, byBody);
}
else
{
MessageBox.Show("socket");
return;
}
}


}

}
满衣兄 2009-07-28
  • 打赏
  • 举报
回复
封包,定义包头包尾.
stning 2009-07-28
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 czjearth 的回复:]
楼主能否说详细些,

大文件分段, 那和发小文件有何区别?

[/Quote]丢包,通过网络传输,各种问题就可能有
czjearth 2009-07-28
  • 打赏
  • 举报
回复


把文件读到 流中, 分段发送就是
stning 2009-07-28
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 jsoner 的回复:]
将文件分段传送,每次传送8KB。

先定义一个单个数据包的最大长度 
然后发送文件。如果大小超过单个包大小就拆分后发送。 
接收段只需要把数据拼合起来就好了。 
[/Quote]200分的帖子,等到现在才sf。。汗
czjearth 2009-07-28
  • 打赏
  • 举报
回复
楼主能否说详细些,

大文件分段, 那和发小文件有何区别?
加载更多回复(17)
《Windows Sockets网络编程》是WindowsSockets网络编程领域公认的经典著作,由Windows Sockets2.0规范解释小组负责人亲自执笔,权威性毋庸置疑。它结合大量示例,对WindowsSockets规范进行了深刻地解读,系统讲解了WindowsSockets网络编程及其相关的概念、原理、主要命令、操作模式,以及开发技巧和可能的陷阱,从程序员的角度给出了大量的建议和最佳实践,是学习WindowsSockets网络编程不可多得的参考书。   全书分为三部分:第一部分(第1~6章),提供了翔实的背景知识和框架方面的概念,借助于此框架,读者可理解WinSock的具体细节,包括WindowsSockets概述、OSI网络参考模型、TCP/IP协议簇中的协议和可用的服务、WinSock网络应用程序的框架及其工作机制、WinSock的三种操作模式、socket通信机制等;第二部分(第7~12章),以FTP客户端实例为基础介绍了函数实例库,还介绍了客户端程序、服务器程序和DLL中间构件及它们的相应函数,并涵盖socket命令和选项及移植BSDSockets相关事项等;第三部分(第13~17章),介绍了应用程序调试技术和工具,针对应用编程中的陷阱的建议和措施,WinSockAPI的多种操作系统平台,WinSock规范的可选功能和WinSock规范2.0中的所有新功能。 译者序 序 前言 第1章 Windows Sockets概述 1.1 什么是Windows Sockets 1.2 Windows Sockets的发展历史 1.3 Windows Sockets的优势 1.3.1 Windows Sockets是一个开放的标准 1.3.2 Windows Sockets提供源代码可移植性 1.3.3 Windows Sockets支持动态链接 1.3.4 Windows Sockets的优点 1.4 Windows Sockets的前景 1.5 结论 第2章 Windows Sockets的概念 2.1 OSI网络模型 2.2 WinSock网络模型 2.2.1 信息与数据 2.2.2 应用协议 2.3 WinSock中的OSI层次 2.3.1 应用层 2.3.2 表示层 2.3.3 会话层 2.3.4 传输层 2.3.5 网络层 2.3.6 数据链路层 2.3.7 物理层 2.4 模块化的层次框 2.5 服务和协议 2.6 协议和API 第3章 TCP/IP协议服务 3.1 什么是TCP/IP 3.2 TCP/IP的发展历史 3.3 传输服务 3.3.1 无连接的服务:UDP 3.3.2 面向连接的服务:TCP 3.3.3 传输协议的选择:UDP与TCP的对比 3.4 网络服务 3.4.1 IP服务 3.4.2 ICMP服务 3.5 支持协议和服务 3.5.1 域名服务 3.5.2 地址解析协议 3.5.3 其他支持协议 3.6 TCP/IP的发展前景 第4章 网络应用程序工作机制 4.1 客户端-服务器模型 4.2 网络程序概览 4.3 socket的打开 4.4 socket的命名 4.4.1 sockaddr结构 4.4.2 sockaddr_in结构 4.4.3 端口号 4.4.4 本地IP地址 4.4.5 什么是socket名称 4.4.6 客户端socket名称是可选的 4.5 与另一个socket建立关联 4.5.1 服务器如何准备建立关联 4.5.2 客户端如何发起一个关联 4.5.3 服务器如何完成一个关联 4.6 socket之间的发送与接收 4.6.1 在“已连接的”socket发送数据 4.6.2 在“无连接的”socket发送数据 4.6.3 接收数据 4.6.4 socket解复用器中的关联 4.7 socket的关闭 4.7.1 closesocket 4.7.2 shutdown 4.8 客户端和服务器概览 第5章 操作模式 5.1 什么是操作模式 5.1.1 不挂机,等待:阻塞 5.1.2 挂机后再拨:非阻塞 5.1.3 请求对方回拨:异步 5.2 阻塞模式 5.2.1 阻塞socket 5.2.2 阻塞函数 5.2.3 伪阻塞的问题 5.2.4 阻塞钩子函数 5.2.5 阻塞情境 5.2.6 撤销阻塞操作 5.2.7 阻塞操作中的超时 5.2.8 无最少接收限制值 5.2.9 代码示例 5.3 非阻塞模式 5.3.1 怎样使socket成为非阻塞的 5.3.2 成功与失败不是绝对的 5.3.3 探询而非阻塞 5.3.4 显式地避让 5.3.5 代码示例 5.4 异步模式 5.4.1 认识异步函数 5.4.2 撤销异步操作 5.4.3 代码示例 5.4.4 AU_T
《Windows Sockets网络编程》是WindowsSockets网络编程领域公认的经典著作,由Windows Sockets2.0规范解释小组负责人亲自执笔,权威性毋庸置疑。它结合大量示例,对WindowsSockets规范进行了深刻地解读,系统讲解了WindowsSockets网络编程及其相关的概念、原理、主要命令、操作模式,以及开发技巧和可能的陷阱,从程序员的角度给出了大量的建议和最佳实践,是学习WindowsSockets网络编程不可多得的参考书。   全书分为三部分:第一部分(第1~6章),提供了翔实的背景知识和框架方面的概念,借助于此框架,读者可理解WinSock的具体细节,包括WindowsSockets概述、OSI网络参考模型、TCP/IP协议簇中的协议和可用的服务、WinSock网络应用程序的框架及其工作机制、WinSock的三种操作模式、socket通信机制等;第二部分(第7~12章),以FTP客户端实例为基础介绍了函数实例库,还介绍了客户端程序、服务器程序和DLL中间构件及它们的相应函数,并涵盖socket命令和选项及移植BSDSockets相关事项等;第三部分(第13~17章),介绍了应用程序调试技术和工具,针对应用编程中的陷阱的建议和措施,WinSockAPI的多种操作系统平台,WinSock规范的可选功能和WinSock规范2.0中的所有新功能。 译者序 序 前言 第1章 Windows Sockets概述 1.1 什么是Windows Sockets 1.2 Windows Sockets的发展历史 1.3 Windows Sockets的优势 1.3.1 Windows Sockets是一个开放的标准 1.3.2 Windows Sockets提供源代码可移植性 1.3.3 Windows Sockets支持动态链接 1.3.4 Windows Sockets的优点 1.4 Windows Sockets的前景 1.5 结论 第2章 Windows Sockets的概念 2.1 OSI网络模型 2.2 WinSock网络模型 2.2.1 信息与数据 2.2.2 应用协议 2.3 WinSock中的OSI层次 2.3.1 应用层 2.3.2 表示层 2.3.3 会话层 2.3.4 传输层 2.3.5 网络层 2.3.6 数据链路层 2.3.7 物理层 2.4 模块化的层次框 2.5 服务和协议 2.6 协议和API 第3章 TCP/IP协议服务 3.1 什么是TCP/IP 3.2 TCP/IP的发展历史 3.3 传输服务 3.3.1 无连接的服务:UDP 3.3.2 面向连接的服务:TCP 3.3.3 传输协议的选择:UDP与TCP的对比 3.4 网络服务 3.4.1 IP服务 3.4.2 ICMP服务 3.5 支持协议和服务 3.5.1 域名服务 3.5.2 地址解析协议 3.5.3 其他支持协议 3.6 TCP/IP的发展前景 第4章 网络应用程序工作机制 4.1 客户端-服务器模型 4.2 网络程序概览 4.3 socket的打开 4.4 socket的命名 4.4.1 sockaddr结构 4.4.2 sockaddr_in结构 4.4.3 端口号 4.4.4 本地IP地址 4.4.5 什么是socket名称 4.4.6 客户端socket名称是可选的 4.5 与另一个socket建立关联 4.5.1 服务器如何准备建立关联 4.5.2 客户端如何发起一个关联 4.5.3 服务器如何完成一个关联 4.6 socket之间的发送与接收 4.6.1 在“已连接的”socket发送数据 4.6.2 在“无连接的”socket发送数据 4.6.3 接收数据 4.6.4 socket解复用器中的关联 4.7 socket的关闭 4.7.1 closesocket 4.7.2 shutdown 4.8 客户端和服务器概览 第5章 操作模式 5.1 什么是操作模式 5.1.1 不挂机,等待:阻塞 5.1.2 挂机后再拨:非阻塞 5.1.3 请求对方回拨:异步 5.2 阻塞模式 5.2.1 阻塞socket 5.2.2 阻塞函数 5.2.3 伪阻塞的问题 5.2.4 阻塞钩子函数 5.2.5 阻塞情境 5.2.6 撤销阻塞操作 5.2.7 阻塞操作中的超时 5.2.8 无最少接收限制值 5.2.9 代码示例 5.3 非阻塞模式 5.3.1 怎样使socket成为非阻塞的 5.3.2 成功与失败不是绝对的 5.3.3 探询而非阻塞 5.3.4 显式地避让 5.3.5 代码示例 5.4 异步模式 5.4.1 认识异步函数 5.4.2 撤销异步操作 5.4.3 代码示例 5.4.4 AU_T
信息工程学院计算机网络 课程研究报告 题目全称: 端口扫描工具设计 课 程: 计算机网络 学 号: 班 级: 姓 名: 摘要 在现在这个信息化的社会中,网络的发展已经超出了人们预想,在很短的时间里已经渗透到军事,金融,商业,交通,电信,教育等领域,并发挥着越来越大的作用。社会对网络系统的依赖也越来越强,使得密集信息和财富高度集中与计算机中。另一方面,这些网络系统都依靠计算机网络接受和处理信息,实现其相互间的联系和对目标的管理与控制。而网络端口扫描作为维护网络安全的重要手段,可以帮助服务器提供商找出自身漏洞,避免黑客攻击;测试远程服务器的端口是否可达,防止沿途运营商、防火墙限制了端口导致服务不可用。 .备注 本次计算机网络课程设计我主要是学习一下端口扫描工具的基本知识以及研究别人做出的端口扫描工具,以下即是本次研究的相关研究报告。鉴于自己计算机方面知识不是很好,不足之处还请老师指出与修正。 端口扫描器的研究 TCP协议介绍 提到端口扫描技术就不可不提及TCP协议了,作为互联网的核心协议,TCP协议的重要性是人人皆知,端口扫描主要是建立在TCP协议基础上的一门技术。TCP协议是一种面向连接的,可靠的传输协议。一次正常的TCP传输需要通过在客户和服务器之间建立特定的虚电路连接来完成,这个过程通常被称为"三次握手"。TCP通过数据分段中的序列号保证所有的传输数据可以在远端按照正常的次序重组,而通过确认保证数据传输的完整性。 三次握手过程: 1:客户端发送一个TCP包(SYN请求)给服务端,其中标记SYN(同步序号)要打开。SYN请求指明了客户端希望连接的服务器端端口号和客户端的ISN。 2:服务器端发回应答,包含自己的SYN信息ISN和对客户端的SYN应答,应答时返回下一个希望得到的字节序号。 3:客户端对从S服务器端来的SYN进行应答,数据发送开始。 UDP协议介绍 UDP,用户数据报协议。UDP为应用程序提供了一种方法发送经过封装的IP数据报,而且不必建立连接就可以发送这些IP数据报。 UDP传输的数据段是由8个字节的头和净荷域构成的。两个端口分别被用来标识出源机器和目标机器内部的端点。当一个UDP分组到来的时候,它的净荷部分被递交给与目标端口相关联的那个进程。当目标端口必须将一个应答送回给源端口的时候,源端口是必须的。发送应答的进程只要将近来的数据段中的源端口域复制到输出的数据段中的目标端口域,就可以指定在发送机器上有哪个进程来接受应答。UDP长度包含了8字节的头和数据部分。UDP校验和是可选的,如果不计算的话,则在该域中存放0,如果真正的计算结果试的话,则该域中存放的全是1,除非数据 的质量并不重要,否则就不应该将校验和的功能关闭。另外值得明确提出来的是UDP没有做到的一些事情。UDP并不考虑流控制,错误控制,在收到一个坏的数据段之后它也不重传。所有这些工作都留给用户的进程。UDP所作的事情是提供一个接口,并且 接口中增加解复用的特性。他利用端口的概念将数据段解复用到多个进程中,这就是他所做的全部工作。 SOCKET介绍 Socket接口是TCP/IP网络的API,Socket接口定义了许多函数或例程,程序员可以用它们来开发TCP/IP网络上的应用程序。要学Internet上的TCP/IP网络编程,必须理解Socket接口。 Socket接口设计者最先是将接口放在Unix操作系统里面的。如果了解Uinx系统的输入和输出的话,就很容易了解Socket了。网络的Socket数据传输是一种特殊的I/O,Socket也是一种文件描述符。Socket也具有一个类似于打开文件的函数调用Socket(),该函数返回一个整型的Socket描述符,随后的连接建立,数据传输等操作都是通过该Socket实现的。 Sockfd是需要关闭的socket的描述符。参数 how允许为shutdown操作选择以下几种方式: ·0-------不允许继续接收数据 ·1-------不允许继续发送数据 ·2-------不允许继续发送和接收数据,均为允许则调用close ()   shutdown在操作成功时返回0,在出现错误时返回-1并置相应errno。 常用端口扫描技术 TCP connect()扫描: 这是最基本的TCP扫描,操作系统提供的connect()系统调用可以用来与每一个感兴趣的目标计算机的端口进行连接。如果端口处于侦听状态,那么connect()就能成功。否则,这个端口是不能用的,即没有提供服务。这个技术的一个最大的优点是,你不需要任何权限。系统中的任何用户都有权利使用这个调用。另一个好处就是速度,如果对每个目标端口以线性的方式,使用单独的connect()调用,那么将会花费相当长的时间,使用者可以通过同时打开多个套接字来加速扫描。使用非阻

110,538

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧