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;
}
非阻塞模型,能够在发送过程当中进行读取操做,提升了效率。
固然,在第二次发送前,必须等待第一次发送操做完成才行,须要检测和控制!socket
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 方法。
下面的代码示例异步接收来自远程主机的无链接数据报。
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());
}ide
在端口 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());
}函数