6

I have created a simple server using socket programming in C# which will receive a file from the client side. My sample code segment is given below.

I want to add some restrictions. I want to make a limit on the file size (such as 4 KB or 2 KB) and allowable file formats (such as .doc, .txt, .cpp, etc.) which will be sent to the client as soon as the client connects to the server so that the client can send files accordingly. How will I do that?

Sample code segment:

using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Text;

namespace FileTransfer
{
    class Program
    {
        static void Main(string[] args)
        {
            // Listen on port 1234

            TcpListener tcpListener = new TcpListener(IPAddress.Any, 1234);
            tcpListener.Start();

            Console.WriteLine("Server started");

            //Infinite loop to connect to new clients
            while (true)
            {
                // Accept a TcpClient
                TcpClient tcpClient = tcpListener.AcceptTcpClient();
                                Console.WriteLine("Connected to client");
                byte[] data = new byte[1024];
                NetworkStream ns = tcpClient.GetStream();
                int recv = ns.Read(data, 0, data.Length);
                StreamReader reader = new StreamReader(tcpClient.GetStream());

               //Will add some lines to add restrictions...

            }
        }
    }
}

Which additional lines will I have to add to the code to send the restrictions to client?

3
  • 1
    To make a limit on the file size just add total data size counter, like "int counter = 0; counter += recv;". Then if limit exceeded drop client with appropriate message. Commented Sep 27, 2015 at 8:47
  • I just want to send the file size and allowable file formats to the client as sson as the client connects so that the client can send files accordingly @Alek Depler Commented Sep 27, 2015 at 8:51
  • Hm, then you have to create your own client-server protocol. Both client and server can send data to each other, you need to split all data by two types: technical protocol instructions and the data itself. The answer by "CodeCaster" is correct Commented Sep 27, 2015 at 8:54

2 Answers 2

4

Basically I think mainly you need two things:

  • define application protocol as suggested in other answer

  • and handle partial read/writes

For handling partial reads (not sure how much such function is needed for write) you may use function like below:

public static void ReadWholeArray (Stream stream, byte[] data)
{
    int offset=0;
    int remaining = data.Length;
    while (remaining > 0)
    {
        int read = stream.Read(data, offset, remaining);
        if (read <= 0)
            throw new EndOfStreamException 
                (String.Format("End of stream reached with {0} bytes left to read", remaining));
        remaining -= read;
        offset += read;
    }
}

Thing is traditional Stream.Read() doesn't guarantee to read as many bytes as you told it, this method on the other hand, will ensure to have read as many bytes as specified in data.Length parameter. So you can use such function to implement the desired application protocol instead.

Some relevant information about such application protocols you will find here too


Ok this is for example how the server could send file length limit and the file extension:

// Send string
string ext = ".txt";
byte [] textBytes = Encoding.ASCII.GetBytes(ext);
ns.Write(textBytes, 0, textBytes.Length); 

// Now, send integer - the file length limit parameter
int limit = 333;
byte[] intBytes = BitConverter.GetBytes(limit);
ns.Write(intBytes, 0, intBytes.Length); // send integer - mind the endianness

But you will still need some kind of protocol otherwise you should let client read the "full" stream and parse these data later somehow, which isn't trivial if the data doesn't have fixed length etc - otherwise how will the client distinguish which part of the message is text, which integer?

Sign up to request clarification or add additional context in comments.

8 Comments

Have an upvote for linking to Beej's guide. Anyone even remotely interested in network programming should have read that guide at least once.
@CodeCaster:Yes, indeed, thanks. That guide contains useful information. OP will need to handle partial send/receives, and think of some protocol, like you suggest, or TLV, etc.
The protocol I suggest is TLV, AFAIK. :-)
@CodeCaster: ok, thought so initially:) maybe you can a bit reword it to make more understandable for OP (more easily explained). but that as well might not be necessary
But I want to send the constraints to the client when it it connected so that it can send files according to the constraints. I want to check it from the client side not from the server side. From the server side, I just want to send the constraints @Giorgi
|
3

You seem to be making the classical socket mistake. The given code and explanation seem to assume sockets handle in messages. They don't. When used this way, you're using streaming internet sockets, which provide a stream, not messages.

You don't show any code that does the actual sending, so I'm guessing that you just pump a file's data to the other side and close the connection. How else will you know you've successfully transferred an entire file?

This set of rules that client and server have to follow in order to usefully exchange data through sockets is called an application protocol. You will have to have one, otherwise you'll just be sending data to $deity knows where, and you'll have no control over it at all. This means server nor client will know what's going on, they'll just be sending and receiving data and hoping all goes well. So there's not "a few lines" you have to add to your code, you'll have to restructure it entirely.

There are many ways to define an application protocol and many options to choose from, so I'm going to show you an arbitrary one: a textual explanation of messages that are prefixed with an ID and a payload length (if applicable), both in unspecified numeric variables. You could choose little-endian four-byte unsigned integers, for example.

Messages in this format are known as "Type/Length/Value" or TLV. So we define these messages:

ID  Name         Direction         Description                    Payload
1   ServerHello  Server -> Client  The server sends this message  None. 
                                   to every connecting client.    Or maybe server or 
                                                                  protocol version.
2   MaxUpload    Server -> Client  Sent after the ServerHello.    Maximum upload size 
                                                                  in bytes.
3   AllowedExts  Server -> Client  Allowed upload extensions,     The allowed extensions. 
                                   comma-separated. Sent after 
                                   MaxUpload message.
10  IncomingFile Client -> Server  There's a file coming.         The file name.
11  FileUpload   Client -> Server  The file to upload.            The file data.
                                   Sent after IncomingFile.

Now all that's required is to implement this application protocol in server and client and you're done.

You also have to decide what to do if a client or server doesn't adhere to the prototol. It can for example send a message that you can't parse, an unknown message ID, a message length that you don't want to support, an out-of-order message (FileUpload before IncomingFile) or a message that isn't conform the messages sent earlier, like a client uploading a larger file than the server said it would accept or an invalid extension. You also have to think about "acknowledgement" or response messages, like the server telling the client "OK, go ahead, send the next message".

All in all, this is a very broad question and not answered easily. I tried to address that in my comment to your question, which got removed. So here you have your answer.

You can learn more about this on the web, for example Beej's Guide to Network Programming as linked to by Giorgi (be sure to read the entire guide) and Stephen Cleary's blog.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.