首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > .NET > C# >

socket 客户端收到的数据与服务器发送不一致有关问题

2012-03-19 
socket 客户端收到的数据与服务器发送不一致问题小弟在搭建一c/s架构的通信程序。现在遇到socket客户端收到

socket 客户端收到的数据与服务器发送不一致问题
小弟在搭建一c/s架构的通信程序。现在遇到socket   客户端收到的数据与服务器发送不一致问题。客户端收到的数据总是比服务器端发送的少一点。如果在客户端程序中设置断点调试就能收全。百思不得其解,请各位高手帮助解决。
注:(所有测试都在局域网内进行)
服务器端使用ReadToEnd()方法将一文件一次性读出,然后再转换成UTF8码,再使用clientsocket.Send()方法一次传送给客户端。

客户端部分代码如下:
namespace   client
{

        public   class   client
        {
                static   Socket   serverSocket   =   null;
                private   static   Socket   ConnectSocket(string   server,   int   port)
                {
                        Socket   s   =   null;
                        IPHostEntry   hostEntry   =   null;
               
                        //   Get   host   related   information.
                        hostEntry   =   Dns.GetHostEntry(server);

                        //   Loop   through   the   AddressList   to   obtain   the   supported   AddressFamily.   This   is   to   avoid
                        //   an   exception   that   occurs   when   the   host   IP   Address   is   not   compatible   with   the   address   family
                        //   (typical   in   the   IPv6   case).
                        foreach(IPAddress   address   in   hostEntry.AddressList)
                        {
                                IPEndPoint   ipe   =   new   IPEndPoint(address,   port);
                                Socket   tempSocket   =new   Socket(ipe.AddressFamily,   SocketType.Stream,   ProtocolType.Tcp);

                                tempSocket.Connect(ipe);

                                if(tempSocket.Connected)
                                {
                                        s   =   tempSocket;
                                        break;
                                }
                                else


                                {
                                        continue;
                                }
                        }
                        return   s;
                }
       

                //   This   method   requests   the   home   page   content   for   the   specified   server.
                private   static   string   SocketSendReceive(string   server,   int   port)  
                {
                        string   request   =   "GET   /   HTTP/1.1\r\nHost:   "   +   server   + "\r\nConnection:   Close\r\n\r\n ";
                        Byte[]   bytesSent   =   Encoding.ASCII.GetBytes(request);
                        Byte[]   bytesReceived   =   new   Byte[256];
             
                        //   Create   a   socket   connection   with   the   specified   server   and   port.
                        Socket   s   =   ConnectSocket(server,   port);

                        if   (s   ==   null)
                                return   ( "Connection   failed ");
           
                        //   Send   request   to   the   server.
                        serverSocket   =   s;
                        s.Send(bytesSent,   bytesSent.Length,   0);    
               
                        //   Receive   the   server   home   page   content.
                        Int32   bytes   =   0;
                        string   page   =   "Default   HTML   page   on   "   +   server   +   ":\r\n ";

                        //   The   following   will   block   until   te   page   is   transmitted.



                        bytes   =   s.Receive(bytesReceived,   bytesReceived.Length,   0);
                        page   =   page   +   Encoding.ASCII.GetString(bytesReceived,   0,   bytes);
                        while(s.Available> 0)
                        {
                                bytes   =   s.Receive(bytesReceived,bytesReceived.Length,0);
                                page   =   page   +   Encoding.ASCII.GetString(bytesReceived,   0,   bytes);
                        }
                        Console.WriteLine( "\n ");
                        Console.WriteLine(bytes);                
                        return   page;
                }

                private   static   void   SocketSendData(Socket   s)
                {
                        String   str   =   Console.ReadLine();
                        Byte[]   bytesSent   =   Encoding.ASCII.GetBytes(str);
                        s.Send(bytesSent,   bytesSent.Length,   0);

                }
                private   static   string   SocketReceiveData(Socket   s)
                {

                        //   Receive   the   server   home   page   content.
                        Byte[]   bytesReceived   =   new   Byte[256];
                        Int32   bytes   =   0;
                        string   recvStr   =   " ";

                        //   The   following   will   block   until   te   page   is   transmitted.
                        bytes   =   s.Receive(bytesReceived,   bytesReceived.Length,   0);
                        recvStr   =   recvStr   +   Encoding.ASCII.GetString(bytesReceived,   0,   bytes);
                        while   (s.Available   >   0)


                        {
                                bytes   =   s.Receive(bytesReceived,   bytesReceived.Length,   0);
                                recvStr   =   recvStr   +   Encoding.ASCII.GetString(bytesReceived,   0,   bytes);
                        }
                        Console.WriteLine( "\n ");
                        Console.WriteLine(bytes);
                        return   recvStr;
                }

                public   static   void   Main()
                {
                        try
                        {      
                                string   host;
                                int   port   =   8001;
                                host   =   "192.168.1.212 ";
                                string   result   =   SocketSendReceive(host,   port);  
                                Console.WriteLine(result);
                                Console.WriteLine( "\n--------------- ");

                                Console.WriteLine( "\n第二次发送数据\n ");
                                SocketSendData(serverSocket);
                                Console.WriteLine( "\n第二次发送完毕!\n ");
                                Console.WriteLine( "\n--------------- ");

                                Console.WriteLine( "\n第二次接收数据\n ");
                                Console.WriteLine(SocketReceiveData(serverSocket));
                                Console.WriteLine( "\n第二次接收完毕!\n ");
                                Console.WriteLine( "\n--------------- ");


                                String   str   =   Console.ReadLine();
                                serverSocket.Close();
                        }
                        catch   (Exception   e)
                        {
                                Console.WriteLine( "Error.....   "   +   e.StackTrace);
                        }
                }
        }
}

[解决办法]
丢失数据可能是缓冲小,里面的数据还没处理就被server发送的下一批数据覆盖了。有两个方法解决,一个是让server每交发送时间间隔大点。第二个就是在client端采用socket的异步接收处理。
个人推荐使用第二种方法,msdn中在socket里有相关的异步处理说明和例子,你可以看看。

[解决办法]
using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Net.Sockets;
using System.Threading;
using System.Net;
using System.Text;
using System.IO;
namespace SocketRun
{
public partial class _Default : System.Web.UI.Page
{
public static ManualResetEvent allDone = new ManualResetEvent(false);
protected void Page_Load(object sender, EventArgs e)
{
string host = @ "192.168.1.1 ";
int port = 3000;
#region 测试数据
//string host = @ "http://www.um114.com ";
//int port = 8000;

//Socket tempSocket = new Socket(IPAddress.Parse(host).AddressFamily,
// SocketType.Stream,
// ProtocolType.Tcp);
//tempSocket.Connect(IPAddress.Parse(host), port);
//if (tempSocket.Connected)
// this.lbInfo.Text = "Ok ";

#endregion
try
{
SocketSendReceive(host, port);
}
catch(Exception ex)
{
this.lbInfo.Text = ex.Message;
}

}
/// <summary>
/// 发起一次异步连接尝试
/// </summary>
/// <param name= "ar "> </param>
private void ConnectCallback(IAsyncResult ar)
{
allDone.Set();
Socket s = (Socket)ar.AsyncState;
s.EndConnect(ar);
}
/// <summary>
/// Asynchronous connect using the host name
/// </summary>
/// <param name= "host "> </param>
/// <param name= "port "> </param>
private Socket ConnectSocket(string host, int port)
{
Socket s = null;
#region 测试数据
//IPHostEntry hostEntry = null;
//try


//{
// hostEntry = Dns.GetHostEntry(host);
//}
//catch (Exception ex)
//{
// this.lbInfo.Text = ex.Message;
// return null;
//}
//IPAddress address = hostEntry.AddressList[0];
//IPEndPoint ipe = new IPEndPoint(address, port);
#endregion
IPEndPoint ipe = new IPEndPoint(IPAddress.Parse(host), port);
Socket tempSocket = new Socket(ipe.Address.AddressFamily,SocketType.Stream,ProtocolType.Tcp);
allDone.Reset();
try
{
tempSocket.BeginConnect(ipe, new AsyncCallback(ConnectCallback), tempSocket);
}
catch (Exception ex)
{
this.lbInfo.Text = ex.Message;
}
// wait here until the connect finishes.
// The callback sets allDone.
allDone.WaitOne();
if (tempSocket.Connected)
{
s = tempSocket;
}
return s;
}
/// <summary>
/// This method requests the home page content for the specified server.
/// </summary>
/// <param name= "server "> </param>
/// <param name= "port "> </param>
/// <returns> </returns>
private void SocketSendReceive(string server, int port)
{
//取得预保存的文件名
string fileName = "d:\\1.txt ";
//发送给远程主机的请求内容串
//string request = "GET / HTTP/1.1\r\nHost: " + server +
// "\r\nConnection: Close\r\n\r\n ";
string request = "kw=日本人&page=1 ";
//创建bytes字节数组以转换发送串
Byte[] bytesSent = Encoding.Default.GetBytes(request);
//声明字节数组,一次接收数据的长度为1024字节
Byte[] bytesReceived = new Byte[1024];
// Create a socket connection with the specified server and port.
Socket s = ConnectSocket(server, port);
if (s == null)
return;//( "Connection failed ");
//设置为非阻塞状态
s.Blocking = false;
// //向主机发送请求
s.Send(bytesSent, bytesSent.Length, 0);

// //声明接收返回内容的字符串
int bytes = 0;
string page = " ";
//string page = "Default HTML page on " + server + ":\r\n ";

// //循环读取,直到接收完所有数据
do
{
bytes = s.Receive(bytesReceived, bytesReceived.Length, 0);
page = page + Encoding.Default.GetString(bytesReceived, 0, bytes);
}
while (bytes > 0);
//将所读取的字符串转换为字节数组
byte[] content = Encoding.ASCII.GetBytes(page);
try
{
//创建文件流对象实例
FileStream fs = new FileStream(fileName, FileMode.OpenOrCreate, FileAccess.ReadWrite);
//写入文件
fs.Write(content, 0, content.Length);
fs.Close();
fs.Dispose();
}
catch (Exception fe)
{
this.lbInfo.Text = "文件创建/写入错误: " + fe.Message;
}
s.Blocking = true;
//禁用Socket
s.Shutdown(SocketShutdown.Both);


//关闭Socket
s.Close();
}


}
}

[解决办法]
把数据包组包中加入结束符,然后在接收后判断。如果缓存区很小,可以接收两次后组包显示。

热点排行