C# .NET - TCP Messages are fragmented in Win7 if datasize is more than 1074 byte

Asked By Nagaraja
23-Aug-11 04:28 AM
I have used simple Socket class from .NET framework to send and receive data messages through TCP. When I run my tcp client app on Windows XP, then the data message is not fragmented. But when I run same tcp client app on Windows 7, the data messages are fragmented when the data message size is more than 1074 bytes.

IPEndPoint ipEndPoint = new IPEndPoint("<server ip address>", 601);

Socket tcpSocket = new Socket(ipEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);

tcpSocket.Connect(ipEndPoint.Address, ipEndPoint.Port);
tcpSocket .Send(data, data.Length, 0);

tcpSocket.Close();


Please let me know if you have any suggestions.
  James H replied to Nagaraja
23-Aug-11 04:36 AM
using the socket object directly (rather than the TCP client). I create a Server object that looks something like this (I've edited some stuff such as exception handling out for brevity, but I hope that the idea comes across.).
public
class Server()
{
  private Socket sock;
  // You'll probably want to initialize the port and address in the
  // constructor, or via accessors, but to start your server listening
  // on port 8080 and on any IP address available on the machine...
  private int port = 8080;
  private IPAddress addr = IPAddress.Any;
 
  // This is the method that starts the server listening.
  public void Start()
  {
    // Create the new socket on which we'll be listening.
    this.sock = new Socket(
      addr.AddressFamily,
      SocketType.Stream,
      ProtocolType.Tcp);
    // Bind the socket to the address and port.
    sock.Bind(new IPEndPoint(this.addr, this.port));
    // Start listening.
    this.sock.Listen(this.backlog);
    // Set up the callback to be notified when somebody requests
    // a new connection.
    this.sock.BeginAccept(this.OnConnectRequest, sock);
  }
 
  // This is the method that is called when the socket recives a request
  // for a new connection.
  private void OnConnectRequest(IAsyncResult result)
  {
    // Get the socket (which should be this listener's socket) from
    // the argument.
    Socket sock = (Socket)result.AsyncState;
    // Create a new client connection, using the primary socket to
    // spawn a new socket.
    Connection newConn = new Connection(sock.EndAccept(result));
    // Tell the listener socket to start listening again.
    sock.BeginAccept(this.OnConnectRequest, sock);
  }
}

Then, I use a separate Connection class to manage the individual connection with the remote host. That looks something like this.
public class Connection()
{
  private Socket sock;
  // Pick whatever encoding works best for you.  Just make sure the remote
  // host is using the same encoding.
  private Encoding encoding = Encoding.UTF8;
 
  public Connection(Socket s)
  {
    this.sock = s;
    // Start listening for incoming data.  (If you want a multi-
    // threaded service, you can start this method up in a separate
    // thread.)
    this.BeginReceive();
  }
 
  // Call this method to set this connection's socket up to receive data.
  private void BeginReceive()
  {
    this.sock.BeginReceive(
        this.dataRcvBuf, 0,
        this.dataRcvBuf.Length,
        SocketFlags.None,
        new AsyncCallback(this.OnBytesReceived),
        this);
  }
 
  // This is the method that is called whenever the socket receives
  // incoming bytes.
  protected void OnBytesReceived(IAsyncResult result)
  {
    // End the data receiving that the socket has done and get
    // the number of bytes read.
    int nBytesRec = this.sock.EndReceive(result);
    // If no bytes were received, the connection is closed (at
    // least as far as we're concerned).
    if (nBytesRec <= 0)
    {
      this.sock.Close();
      return;
    }
    // Convert the data we have to a string.
    string strReceived = this.encoding.GetString(
      this.dataRcvBuf, 0, nBytesRec);
 
    // ...Now, do whatever works best with the string data.
    // You could, for example, look at each character in the string
    // one-at-a-time and check for characters like the "end of text"
    // character ('\u0003') from a client indicating that they've finished
    // sending the current message.  It's totally up to you how you want
    // the protocol to work.
 
    // Whenever you decide the connection should be closed, call
    // sock.Close() and don't call sock.BeginReceive() again.  But as long
    // as you want to keep processing incoming data...
 
    // Set up again to get the next chunk of data.
    this.sock.BeginReceive(
      this.dataRcvBuf, 0,
      this.dataRcvBuf.Length,
      SocketFlags.None,
      new AsyncCallback(this.OnBytesReceived),
      this);
 
  }
}

You can use your Connection object to send data by calling its Socket directly, like so...

this.sock.Send(this.encoding.GetBytes("Hello to you, remote host."));

As I said, I've tried to edit the code here for posting, so I apologize if there are any errors in it.


Create New Account
help
Socket problem migrating to Vista Windows 7 My app currently runs C#, .NET v2.0 on Windows Xp / Windows Server 2003, using asynchronous socket communication. I set up my server socket: Socket s = new Socket( AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp ); IPEndPoint ep = new IPEndPoint( IPAddress.Any, 0 ); s.Bind( ep ); int port = ep.Port; The server socket's computer Socket( AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp ); IPAddress ipAddress = Dns.GetHostEntry( computerName, port ).AddressList[0]; IPEndPoint ep = new IPEndPoint( ipAddress, port ); sClient.Bind( ep ); When I run the server socket application on the Vista
a Client / Server using System.Net.Sockets.UdpClient. My server app is running in a Windows XP Pro and Works Well. My client app is running in a iPaq with Windows Mobile 5.0, and works well when in the same network that my server. The try with this two codes above below: 1 - UdpClient udp = new UdpClient(); udp.Connect(new IPEndPoint(IPAddress.Parse("192.168.0.8"), 8000)); udp.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.IpTimeToLive, 2 IPAddress broadcast = IPAddress.Parse("192.168.0.8"); byte[] sendbuf = Encoding.ASCII.GetBytes("Mobile New"); IPEndPoint ep = new IPEndPoint(broadcast, 8000); s.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.IpTimeToLive, 100); s.SendTo(sendbuf, ep); The line aboni andrew@assergs.com .NET Compact Framework Discussions Encoding.ASCII.GetBytes (1) SocketOptionName.IpTimeToLive (1) Windows Mobile 5.0 (1) Windows XP (1) IPEndPoint (1) AddressFamily.InterNetwork (1) SocketOptionLevel.Socket (1) SocketOptionLevel (1) The router needs
some code (see below) that sends an ICMP echo request and that works fine on Windows XP and 2003 but fails on Vista. The code sends the echo request but times out SocketOptionName.ReceiveTimeout, 5000); socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.IpTimeToLive, 32); socket.SendTo(bytesToSend, (EndPoint)new IPEndPoint(IPAddress.Parse("64.26.22.64"), 0)); byte[] responseBytes = new byte[1024]; EndPoint remoteEndPoint = new IPEndPoint(IPAddress.Any, 0); int bytesReceivedCount = socket.ReceiveFrom(responseBytes, ref remoteEndPoint); Console.WriteLine(bytesReceivedCount); } catch (Exception host has failed to respond Console.WriteLine(ex.ToString()); } } } } .NET Framework Discussions SocketOptionName.IpTimeToLive (1) Windows XP (1) SocketOptionName.ReceiveTimeout (1) IPEndPoint (1) AddressFamily.InterNetwork (1) System.Collections.Generic (1) SocketOptionLevel.Socket (1) System.Net.Sockets (1 code (see below) that sends an ICMP echo request and that G> works fine on Windows XP and 2003 but fails on Vista. The code sends G> the echo request but
IPv4) and getting errors. Hello there, I'm trying to port a program over from Windows XP to Windows Vista / Windows 7. It's a firewall application, and I'm having issues, which I believe are due to my computer (Windows 7) having both IPv4 and IPv6 addresses configured. The error that I'm getting is Mode Stacks (which may apply here as well, since I plan on using this on Windows 2000 / XP / Vista / 7 and potentially 2003 / 2008 / R2)- - in which a Microsoft employee posted some code realize that I probably won't be able to use this on anything prior to Windows XP, but I mentioned 2000 to show that I want to include as many platforms