RE: TCP/IP - Sockets appear to be restricted to maximum 65,535 byte transfers

From: Dan Allen (dallen_at_nist.gov)
Date: 03/07/05


Date: Mon, 7 Mar 2005 11:20:39 -0500

Well - documentation aside - TCP sockets are byte streams. The size of the
actual TCP packets are not necessarily related to the application read/write
sizes. Just read and write in chunk sizes of your choosing. The TCP layer will
packetize it at whim anyway.

HTH,

Dan

> -----Original Message-----
> From: Roy Omond [mailto:Roy.Omond@BlueBubble.UK.Com]
> Sent: Monday, March 07, 2005 10:52 AM
> To: Info-VAX@Mvb.Saic.Com
> Subject: TCP/IP - Sockets appear to be restricted to maximum 65,535 byte
> transfers
>
>
> Gentle colleagues,
>
> this is becoming a bit of a showstopper for me:
>
> A very simple pair of programs (Server and Client) are setup
> to transfer a quantity of data via a TCP Socket. The background
> to this is actually in trying to get this to work in UCX v3.3 ECO 3,
> whereas it worked flawlessly (and as per the documentation) in
> vanilla UCX v3.3 (without ECO), running under VAX VMS 6.2.
>
> The problem is easily demonstrated on VMS 7.3-2 (Alpha) with
> TCP/IP Services v5.4 ECO 4, as well as all the versions after
> UCX v3.3 ECO 3 and above (both VAX and Alpha).
>
> The Server process establishes a socket, listens for an accept on the
> socket (which the Client sends), and sends an amount of data down the
> socket to the client. That's it. It works fine with data up to and
> including 65,535 bytes. Beyond this, it returns an error
> ("%system-f-ivbuflen, invalid buffer length").
> I can find no mention in the documentation "TCP/IP Sockets API
> and System Services Programming" of any such restriction on the
> amount of data to transfer.
>
> Here are the 2 small programs:
>
> --- cut here ---
>
> $ create client.c
> #include <errno.h>
> #include <stdio.h>
> #include <sys/types.h>
> #include <sys/socket.h>
> #include <netinet/in.h>
> #include "sys/ioctl.h"
> #include <netdb.h>
> /*
> struct hostent
> *VGetHostByName(char *name)
> {
> struct hostent *h;
> int i;
>
> if (name == NULL)
> {
> return(NULL);
> }
> sethostent( 1 );
>
> while ((h = gethostent()) != NULL)
> {
> if (strcmp(name,h->h_name) == 0) {
> endhostent();
> return(h);
> }
> i = 0;
> while (h->h_aliases[i] != NULL) {
> if (strcmp(name,h->h_aliases[i]) == 0) {
> endhostent();
> return(h);
> }
> i++;
> }
> }
> endhostent();
> return( NULL );
> }*/
>
> main (int argc, char ** argv)
> {
> int sock;
> int byte_count;
> int bcount;
> char data[1000000];
> int sendbuf;
> int len;
>
> static struct hostent *mh,master_host;
> static struct sockaddr_in sin;
>
> if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1)
> {
> perror ("Create Socket:");
> printf ("errno in CreateSock is %d\n", errno);
> return(-1);
> }
>
> if (argc > 1)
> {
> printf ("Connecting to host %s\n", argv[1]);
> mh = GetHostByName(argv[1]);
> if (mh == NULL)
> {
> perror ("GetHostByName:");
> printf ("Can't get host name %s\n", argv[1]);
> close(sock);
> return (-1);
> }
> }
> else
> {
> printf ("Need a host name\n");
> return (-1);
> }
>
> master_host = *mh;
>
> sin.sin_family = master_host.h_addrtype;
> sin.sin_port = 50000;
> memcpy(&sin.sin_addr, master_host.h_addr, master_host.h_length);
>
> if (connect(sock, &sin, sizeof(struct sockaddr_in)) == -1)
> {
> perror ("Connect:");
> return (-1);
> }
>
> len = sizeof(sendbuf);
> if (getsockopt(sock,SOL_SOCKET,SO_SNDBUF,&sendbuf,&len) < 0)
> {
> perror("getsockopt SO_SNDBUF");
> }
> printf("Send buffer %d bytes\n",sendbuf);
>
> while (1)
> {
> ioctl(sock, FIONREAD, &bcount);
>
> if (bcount > 0)
> {
> int cnt = 0;
> if ((bcount = read (sock, (char *)&byte_count,sizeof(int))) == -1)
> {
> perror ("Read data size");
> return (-1);
> }
> printf ("Read %d bytes, count is %d\n", bcount, byte_count);
>
> bcount = 0;
> while (cnt < byte_count)
> {
> if ((bcount = read (sock, data, byte_count - cnt)) == -1)
> {
> perror ("Read data");
> return (-1);
> }
> printf ("Read %d\n", bcount);
> cnt += bcount;
> }
> printf ("Read %d bytes total\n", cnt);
> break;
> }
> }
> }
>
> $ create server.c
> #include <errno.h>
> #include <stdio.h>
> #include <sys/types.h>
> #include <sys/socket.h>
> #include <netinet/in.h>
> #include <ucx$inetdef.h>
>
> int
> writevv (int fd, struct iovec * iov, int iovcnt)
> {
> int total_bytes = 0, bytes, i;
>
> for (i = 0; i < iovcnt; i++)
> {
> bytes = write (fd, iov[i].iov_base, iov[i].iov_len);
> if (bytes == -1)
> {
> perror ("write:");
> return (-1);
> }
> else
> {
> total_bytes += bytes;
> }
> }
> return (total_bytes);
> }
>
> main (int argc, char ** argv)
> {
>
> int serv_sock = -1;
> int client_sock = -1;
> int len;
>
> int data_size = 1000;
>
> if (argc >= 2) data_size = atoi(argv[1]);
>
> if ((serv_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1)
> {
> perror ("Create Socket:");
> printf ("errno in CreateSock is %d\n", errno);
> return(-1);
> }
>
> len=sizeof(data_size);
>
> if (setsockopt(serv_sock,SOL_SOCKET,SO_SNDBUF,&data_size,len) < 0)
> {
> perror("setsockopt SO_SNDBUF");
> }
>
> if (setsockopt(serv_sock,SOL_SOCKET,SO_RCVBUF,&data_size,len) < 0)
> {
> perror("setsockopt SO_RCVBUF");
> }
> printf("Send/Receive buffer %d bytes\n",data_size);
>
> {
> static struct sockaddr_in sin;
> sin.sin_family = htons(AF_INET);
> sin.sin_port = 50000;
> sin.sin_addr.s_addr = htonl(INADDR_ANY);
>
> if (bind(serv_sock, &sin, sizeof(sin)) == -1)
> {
> printf("cannot bind socket to port");
> perror ("Bind:");
> return(-1);
> }
> }
>
> if (listen(serv_sock, 20) == -1)
> {
> printf("cannot set listen(s,20)");
> perror ("Listen:");
> return(-1);
> }
>
> if ((client_sock = accept(serv_sock, NULL, NULL)) > 0)
> {
> struct iovec iov[2];
> int count;
> static char data[1000000];
>
> if (data_size > 1000000) data_size = 1000000;
> iov[0].iov_base = (char *) &data_size;
> iov[0].iov_len = sizeof(int);
> iov[1].iov_base = &data;
> iov[1].iov_len = data_size;
>
> if (writevv(client_sock,iov,2) == -1)
> {
> perror ("writev:");
> return (-1);
> }
> sleep(10);
> }
> }
> $ server:=$u:[xxxx]server
> $ client:=$u:[xxxx]client
> $ spawn/nowait server 65536
> $ client my-node-name
>
>
>
> Any comments ? Any suggestions ? I thinks this, at worst, a
> bug in the Socket implementation, or, at "best", a serious
> omission in the documentation.
>
> Note, as mentioned above, this worked fine in UCX v3.3, but
> not in UCX v3.3 ECO 3 or later.
>
> Many thanks in advance,
>
> Roy Omond
> Blue Bubble Ltd.
>
>



Relevant Pages

  • Re: Socket.Disconnect Method
    ... Although the exception list in the MSDN documentation ... Windows XP SP2. ... An error occurred when attempting to access the socket. ... use the SocketException.ErrorCode property to obtain the specific error code. ...
    (microsoft.public.vsnet.general)
  • Re: Whats in your toolbox?
    ... sizes of solder ... philips head screw driver set ... security bit set (fits in socket wrench) ... wire cutters (2 sizes of cutting blades one for larger solnoid wires ...
    (rec.games.pinball)
  • Re: [Q] How to Forumulate HTTP request using fsockopen() / fputs()
    ... I can find no documentation ... Frame HTTP Request Command. ... Write the command to socket. ... access have FTP access. ...
    (comp.lang.php)
  • Re: Nonblocking send. Is it a BUG in Windows Socket API?
    ... WinSock documentation. ... sendfunction must not return WSAENOBUFS error ... > regardless of the socket is blocking or nonblocking. ...
    (microsoft.public.win32.programmer.networks)
  • Re: Socket.Disconnect Method
    ... According to the documentation for this method, ... An error occurred when attempting to access the socket. ... It looks to me like the underlying error code could have been: ... This method ends the connection and sets the Connected ...
    (microsoft.public.vsnet.general)