• Content count

  • Joined

  • Last visited

Community Reputation

100 Neutral

About MatsVed

  • Rank
  1. Queuing?

    Makes perfect sense, thanks! :)
  2. Queuing?

    This is kind of a general question, but; How do you design and implement a queue system like in WoW, where if a realm has, say, > 3000 players, you are put in a queue and the number of players that are in the queue are kept track of for you until you can play?
  3. Hi! I'm building myself an FTP server, and I did alright until I got to the LIST command. I'm testing against the FileZilla client, and for some reason it insists on sending me LIST even though I've specified that my server supports MLSD. No matter what I do, I can't get the client to accept my directory listing. Here's the code: public static void HandleLISTCmd(string FTPCommand, FTPClient Client) { Client.Send(Encoding.ASCII.GetBytes("150 Opening binary data connection for file list\0")); /*MemoryStream EPLFStream = new MemoryStream(); BinaryWriter Writer = new BinaryWriter(EPLFStream); string[] Files = Directory.GetFiles(GlobalSettings.Default.WorkingDirectory); foreach (string Fle in Files) Writer.Write(Encoding.ASCII.GetBytes(GenerateFileInfo(Fle))); Writer.Flush();*/ Client.ConnectionResetEvent.WaitOne(); Client.SendFile(EPLFStream.ToArray()); foreach (string Fle in Directory.GetFiles(GlobalSettings.Default.WorkingDirectory)) { string FInfo = GenerateFileInfo(Fle); Client.SendFile(Encoding.ASCII.GetBytes(FInfo)); } //By now the filetransfer should be complete, so let the client know... Client.Send(Encoding.ASCII.GetBytes("226 Transfer complete.\0")); } private static string GenerateFileInfo(string Filepath) { FileInfo FInfo = new FileInfo(Filepath); string Size = FInfo.Length.ToString(); TimeSpan TSpan = (FInfo.LastWriteTime - new DateTime(1970, 1, 1)); string Modified = TSpan.TotalSeconds.ToString(); string ReturnStr = "+s" + Size + ",m" + Modified + ",r," + "\t" + FInfo.Name + "\0"; return ReturnStr; } private static string GenerateBinLS(string Filepath) { FileInfo FInfo = new FileInfo(Filepath); string Result = "rw-r--r-- 1 owner group "; Result += RightAlignString(FInfo.Length.ToString(), 13, ' ') + " "; Result += GetMonth(FInfo.LastWriteTime.Month) + " "; if (FInfo.LastWriteTime.Day.ToString().Length > 2) Result += FInfo.LastWriteTime.Day.ToString() + " "; else if (FInfo.LastWriteTime.Day.ToString().Length == 1) Result += " " + FInfo.LastWriteTime.Day.ToString() + " "; else Result += " " + FInfo.LastWriteTime.Day.ToString() + " "; Result += FInfo.LastWriteTime.Hour.ToString() + ":" + FInfo.LastWriteTime.Minute.ToString() + " "; Result += FInfo.Name; return Result; } private static string GetMonth(int Month) { switch (Month) { case 1: return "Jan"; case 2: return "Feb"; case 3: return "Mar"; case 4: return "Apr"; case 5: return "May"; case 6: return "Jun"; case 7: return "Jul"; case 8: return "Aug"; case 9: return "Sep"; case 10: return "Oct"; case 11: return "Nov"; case 12: return "Dec"; } return ""; } private static string RightAlignString(string sString, int nWidth, char cDelimiter) { System.Text.StringBuilder stringBuilder = new System.Text.StringBuilder(); for (int nCharacter = 0; nCharacter < nWidth - sString.Length; nCharacter++) stringBuilder.Append(cDelimiter); stringBuilder.Append(sString); return stringBuilder.ToString(); } I've tried using both GenerateFileInfo() and GenerateBinLS() to generate my LIST response, but no matter which one I use I get an error about the connection having timed out and that the client couldn't receive my directory listing. I've read that the server is supposed to close the data connection, but when I try to do that FileZilla complains that the server has closed the connection. Here is how I open my data connection: /// <summary> /// Handles a PASV command in the FTP protocol. /// PASV asks the server to open a port for data-transfer and send /// it to the client so it can connect. /// </summary> /// <param name="FTPCommand"></param> /// <param name="IP"></param> /// <param name="Client"></param> public static void HandlePASVCmd(string FTPCommand, string IP, FTPClient Client) { IP = IP.Replace(".", ","); if (Client.OpenDataPort((PortNum1 * 256 + PortNum2).ToString())) { Client.Send(Encoding.ASCII.GetBytes("227 Entering Passive Mode (" + IP + "," + CalculatePort() + ")\0")); } else //This should technically never occur. See //for error codes. Client.Send(Encoding.ASCII.GetBytes("425 Cannot open data connection!\0")); } private static int PortNum1 = 10; private static int PortNum2 = 10; private static string CalculatePort() { //The calculation is PortNum1 x 256 + PortNum2 //26100 is the port being used to listen for initial FTP connections. if ((PortNum1 * 256) + PortNum2 != 26100) { string Result = PortNum1.ToString() + "," + PortNum2.ToString(); PortNum1++; PortNum2++; return Result; } else { PortNum1 = PortNum1 + 2; PortNum2 = PortNum2 + 2; return PortNum1.ToString() + "," + PortNum2.ToString(); } } public bool OpenDataPort(string Port) { IPHostEntry HostEntry = Dns.GetHostByName(Dns.GetHostName()); IPAddress Address = HostEntry.AddressList[0]; Logger.LogDebug("DataAddress: " + Address.ToString()); IPEndPoint LocalEP = new IPEndPoint(Address, int.Parse(Port)); m_DatListenerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); m_ConnectingWaitEvent = new AutoResetEvent(false); try { m_DatListenerSocket.Bind(LocalEP); //Don't need a high backlog, since we'll only be listening for one incoming connection. m_DatListenerSocket.Listen(10); m_DatListenerSocket.BeginAccept(new AsyncCallback(OnAcceptDataconnection), m_DatListenerSocket); } catch (SocketException) { return false; } return true; } private void OnAcceptDataconnection(IAsyncResult AR) { Socket AcceptedSocket = m_DatListenerSocket.EndAccept(AR); if (AcceptedSocket != null) { AcceptedSocket.Blocking = false; m_DatSenderSocket = AcceptedSocket; m_ConnectingWaitEvent.Set(); } } Can someone please help me out? :)
  4. Literature available

    Programming Server-Side Applications for Microsoft Windows 2000 Although effectively outdated (this was released in 2000), this is still a really good book if you want to learn about server-side network programming techniques in Windows (which are largely unchanged today). Network Programming for Microsoft Windows, Second Edition This book covers alot of the same ground as the first one, although this one doesn't seem to specifically cover IOCP (which is a shame).
  5. FTP communication

    Thanks for your answers! Now I've gotten to the point where the client wants my server to go into passive mode. So... does that mean I can direct the client to a port that I've already opened, or should I open a new port for each dataconnection? The latter alternative strikes me as a bit... die-hard? Isn't there a limit on how many ports you can have open at the same time? And if you simply receive all data-traffic on the same socket (same port), how do you distinguish data that belongs to one client from data that belongs to another client?
  6. When a Patch Server is trying to communicate with a browser using FTP, should the server turn off TCP_NODELAY? Also, when wanting to communicate asynchronously, would it be considered good etiquette to send '220 Features: p.' ? Oh and what encoding is the most common? ASCII or Unicode?
  7. Please note that select() should never ever be used on Windows because it will limit you to a maximum of 64 possible connections at any one time. On Windows you should be using IOCP. As for Unix, select() will scale up to 1000 users, IIRC. You can review this in the forum FAQ.
  8. Quote:Also ask yourself what your program gains by trimming the array. Is it really that much memory? Are you looking at more than 4096 bytes? (i.e. one page) This isn't about memory. It's about needing to use the line that was read from the file to load a level in Unreal, and to do that I need to have only the levelname, not a bunch of non-ASCII characters at the end... Unreal still crashes btw. I think you are correct about me wanting to know the number of characters in the string... but my current code doesn't seem to be working... : Edit: The string is already being read to it's exacting length. I'm interested in figuring out how to trim the resulting string... [Edited by - MatsVed on May 16, 2010 5:29:52 AM]
  9. Hi! I have a Readline() function to read unicode characters from a file. It worked perfectly, but when I added some functionality to return the exacting length of the line, it made Unreal crash. There's no easy way for me to debug this, since it's run by Unreal (UDK). wchar_t* ReadLine(wifstream *Stream) { wchar_t *Line = new wchar_t[256]; wchar_t ControlChar = '0'; int i = 0; while(ControlChar != '\n') { ControlChar = Stream->get(); cout << ControlChar; Line[i] = ControlChar; i++; if(i == 256) break; } i = i * 2; //Make a string of the right size... wchar_t *RightSize = new wchar_t[i]; for(int j = 0; j <= i; j++) RightSize[j] = Line[j]; return RightSize; } Doesn't a unicode character take 2 bytes? I would have thought that multiplying i with 2 would do the trick... I'm on Windows btw!
  10. Ah! Got it! NewSave.X = lexical_cast<float, wchar_t[]>(X); Correct answer! It's really confusing how pointers are meant to be used instead of arrays sometimes in C++. In C# and Java, you can return arrays from functions. In C++, you cannot. You have to return a pointer. I actually wrote a PointerToArray() function before you answered, but I realized that it didn't work because you can't return arrays.
  11. Quote: ReadLine returns the pointer to some string "57.9322". You then dereference the pointer and pass the pointed to character, which is '5', to lexical_cast. The lextical_cast then tries to convert the wide character '5' to a floating point value. I suspected as much, so I actually tried to do this: NewSave.X = lexical_cast<float, wchar_t[]>(*X); But that got me this error: 1>c:\users\mats.vederhus\documents\visual studio 2008\projects\loadtest\loadtest\loadtest.cpp(80) : error C2664: 'lexical_cast' : cannot convert parameter 1 from 'wchar_t' to 'wchar_t []' Quote:The problem you're having, from the very beginning, is manual string (and memory in general) management. You don't really understand pointers. What is the reason to manage your own strings, instead of using, say, std::wstring? Because UnrealScript treats wchar_t* as strings. But anyways... How do I lexical cast from wchar_t[] to float? Edit: Changed the lexical_cast to this: template <typename Target, typename Source> Target lexical_cast(Source source) { Target target; std::wostringstream os; os << source; std::wistringstream is(os.str()); is >> target; return target; } Now, X is equal to 5. So yeah... that helped. But how do I get the rest of the string passed to the function?
  12. Ok, so now I'm one step further... I figured out that I need to read X, Y and Z as lines too, because they are floating point numbers with a high accuracy. It seems to work... but when I convert the number from float back to an LPWCSTR to check it's value in the MessageBox, it comes out as 53! Does this mean that the lexical_cast from wchar_t to float is not possible? The number on file is 57.9322. Here is the updated code: __declspec(dllexport) Save* LoadGame(wchar_t* LoadPath) { wifstream LoadStream(LoadPath, ios::in); wchar_t *X = new wchar_t[100]; wchar_t Y; wchar_t Z; static Save NewSave; NewSave.LevelName = new wchar_t[100]; NewSave.LevelName = ReadLine(&LoadStream); //LoadStream >> X; X = ReadLine(&LoadStream); NewSave.X = lexical_cast<float, wchar_t>(*X); LoadStream >> Y; NewSave.Y = lexical_cast<float, wchar_t>(Y); LoadStream >> Z; NewSave.Z = lexical_cast<float, wchar_t>(Z); LoadStream.close(); wstringstream WSS; WSS << NewSave.X; //Prints the number 53! MessageBox(NULL, (LPCWSTR)WSS.str().c_str(), TEXT("LoadGame()"), MB_OKCANCEL); return &NewSave; } Edit: I did like this (to confirm that the float was actually 53): cout << "\nX: " << NewSave.X; //Prints the number 53! MessageBox(NULL, (LPCWSTR)WSS.str().c_str(), TEXT("LoadGame()"), MB_OKCANCEL); And the console prints out 53! Why is the floating point number 57.9322 converted to 53? The console output from ReadLine() seems to indicate that 57.9322 is what is actually being read...
  13. Ah! Durrrh. This makes me feel stupid. :) Worked right away now!
  14. Hm. I changed the ReadLine function: wchar_t* ReadLine(wifstream *Stream) { wchar_t *Line = new wchar_t[256]; wchar_t ControlChar = '0'; int i = 0; while(ControlChar != '\n') { ControlChar = Stream->get(); cout << ControlChar; Line[i] = ControlChar; i++; if(i == 256) break; } return Line; } This allows me to see what's being read. The output is as follows: I'm guessing these are ASCII numbers? How do I display them as characters, and why aren't they showing up in my MessageBox?