Server端:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Threading;
namespace Server
{
class Program
{
public static class soc
{
//創建一個socket
public static Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
}
#region use different methods
public static void accOrder()
{
while (true)
{
Console.WriteLine("Server is ready!");
Socket cliSocket = soc.server.Accept();
byte[] buf = new byte[BufSize];
CommandType choice;
//accept commands
int tRead = cliSocket.Receive(buf);
string command = Encoding.UTF8.GetString(buf, 0, tRead);
string order = command.Substring(0, 4);
order = order.ToLower();
string filename;
choice = deaOrder(order);
filename = command.Substring(5);
filename = filename.Trim();
//choice
if (choice == CommandType.Retrieve)
Retrieve(cliSocket, filename);
else if (choice == CommandType.Store)
Store(cliSocket, filename);
else if (choice == CommandType.Status)
Status(cliSocket, filename);
else
Invalid(cliSocket);
}
}
#endregion
#region choose commands
public static CommandType deaOrder(string order)
{
CommandType choice = 0;
switch (order)
{
case "retr": choice = CommandType.Retrieve;
break;
case "stor": choice = CommandType.Store;
break;
case "stat": choice = CommandType.Status;
break;
default: choice = CommandType.InvalidCommand;
break;
}
return choice;
}
#endregion
#region download files
public static void Retrieve(Socket clisocket, string filename)
{
FileStream SendFile = new FileStream(@filename, FileMode.Open, FileAccess.Read);
try
{
byte[] sendBuf = new byte[BufSize];
int fRead = 0;
long tRead = 0;
fRead = SendFile.Read(sendBuf, 0, sendBuf.Length);
while (fRead > 0)
{
clisocket.Send(sendBuf, fRead, SocketFlags.None);
tRead += fRead;
fRead = SendFile.Read(sendBuf, 0, sendBuf.Length);
}
Console.WriteLine("Sent {0} bytes!", tRead);
}
catch (Exception e)
{
Console.WriteLine("error: " + e.Message);
}
finally
{
SendFile.Close();
clisocket.Close();
//Console.ReadKey();
}
}
#endregion
#region upload files
public static void Store(Socket clisocket, string filename)
{
filename = filename.Substring(3);
filename = ".\\" + filename;
FileStream RecFile = new FileStream(filename, FileMode.OpenOrCreate);
int fRead;
long tWrite = 0;
try
{
byte[] buf = new byte[BufSize];
fRead = clisocket.Receive(buf);
while (fRead > 0)
{
RecFile.Write(buf, 0, fRead);
tWrite += fRead;
fRead = clisocket.Receive(buf);
}
}
catch (Exception e)
{
Console.WriteLine("Error: " + e.Message);
}
Console.WriteLine("Received {0} bytes!", tWrite);
RecFile.Close();
clisocket.Close();
Console.ReadKey();
}
#endregion
#region files' length
public static void Status(Socket clisocket, string filename)
{
string message;
FileInfo fileInfo = new FileInfo(filename);
if (!File.Exists(filename))
message = "Sorry, the file does not exist!";
else
message = "The lengh of the file is " + fileInfo.Length + " bytes";
clisocket.Send(Encoding.UTF8.GetBytes(message));
Console.WriteLine("Information have sent");
}
#endregion
#region invalid commands
public static void Invalid(Socket clisocket)
{
string message = "Invalid command!";
clisocket.Send(Encoding.UTF8.GetBytes(message));
Console.WriteLine("Invalid command");
}
#endregion
public enum CommandType { InvalidCommand, Retrieve, Store, Status };
const int BufSize = 4096;
static void Main(string[] args)
{
//bind a IPEndPoint
soc.server.Bind(new IPEndPoint(IPAddress.Any, 23456));
soc.server.Listen(100);
Thread acc = new Thread(accOrder);
acc.Start();
}
}
}
Client端:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.IO;
namespace Client
{
class Program
{
const int BufSize = 4096;
#region tips
public static string ShowOrder()
{
for (int i = 0; i <= 79; i++)
Console.Write('*');
Console.WriteLine("You can use this client to check a file's length, or to upload or download a file");
Console.WriteLine("Each command should follow this format: <ordername> <pathname> <CLRF>");
Console.WriteLine("To download a file, enter \"retr\" and the file's name, to upload, enter \"stor\"");
Console.WriteLine("And to check the file's length, enter \"stat\".");
for (int i = 0; i <= 79; i++)
Console.Write('*');
Console.Write("Now enter your command(\"quit\" to quit):");
string command = Console.ReadLine();
return command;
}
#endregion
#region download files
public static void Retrieve(Socket client, string com, byte[] buf, string filename)
{
client.Send(Encoding.UTF8.GetBytes(com));
filename = filename.Substring(3);
filename = ".\\" + filename;
FileStream RecFile = new FileStream(filename, FileMode.OpenOrCreate);
int fRead;
long tWrite = 0;
try
{
fRead = client.Receive(buf);
while (fRead > 0)
{
RecFile.Write(buf, 0, fRead);
tWrite += fRead;
fRead = client.Receive(buf);
}
}
catch (Exception e)
{
Console.WriteLine("Error: " + e.Message);
}
Console.WriteLine("Received {0} bytes!", tWrite);
RecFile.Close();
client.Close();
}
#endregion
#region upload files
public static void Store(Socket client, string com, byte[] buf, string filename)
{
client.Send(Encoding.UTF8.GetBytes(com));
FileStream SendFile = new FileStream(filename, FileMode.Open, FileAccess.Read);
//嘗試讀取,發送
try
{
int fRead = 0;
long tRead = 0;
fRead = SendFile.Read(buf, 0, buf.Length);
while (fRead > 0)
{
client.Send(buf, fRead, SocketFlags.None);
tRead += fRead;
fRead = SendFile.Read(buf, 0, buf.Length);
}
Console.WriteLine("You have sent {0} bytes!", tRead);
}
catch (Exception e)
{
Console.WriteLine("Error " + e.Message);
}
//關閉文件流,關閉Socket
finally
{
SendFile.Close();
client.Close();
}
}
#endregion
#region files' length
public static void Status(Socket client, string com, byte[] buf)
{
client.Send(Encoding.UTF8.GetBytes(com));
int tRead = client.Receive(buf);
string message = Encoding.UTF8.GetString(buf, 0, tRead);
Console.WriteLine(message);
}
#endregion
#region invalid commands
public static void Invalid(Socket client, string com, byte[] buf)
{
client.Send(Encoding.UTF8.GetBytes(com));
int tRead = client.Receive(buf);
string message = Encoding.UTF8.GetString(buf, 0, tRead);
Console.WriteLine(message);
}
#endregion
static void Main(string[] args)
{
string com = ShowOrder();
if (com == "quit" || com.Length < 4)
{
Console.WriteLine("Goodbye");
}
else
{
string order = com.Substring(0, 4);
order = order.ToLower();
string filename = com.Substring(5);
filename = filename.Trim();
Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
client.Connect("localhost", 23456);
if (client.Connected)
Console.WriteLine("connect successfully!");
byte[] buf = new byte[BufSize];
switch (order)
{
case "retr": Retrieve(client, com, buf, filename);
break;
case "stor": Store(client, com, buf, filename);
break;
case "stat": Status(client, com, buf);
break;
default: Invalid(client, com, buf);
break;
}
Console.ReadKey();
client.Close();
}
}
}
}
符合的要求:
現定義兩種命令:stat <pathname><CRLF> ①
與 retr<pathname><CRLF> ②
1, <pathname>爲路徑名,或爲絕對路徑(若爲絕對路徑則以字符’/’開頭),或爲相對路徑。
2, <CRLF>爲”\r\n”兩個字符組成的字符串,爲命令的分隔符。
3, 除參數外,命令名不區分大小寫,即stat、Stat、STAT、StAt都一樣。
4, 命令以UTF-8格式傳輸,例子請看AppendixI。
命令功能:
① 請求獲取文件屬性(目前只有長度),以字符串的形式返回。
② 請求建立連接,並開始從服務器中下載<pathname>文件。
服務器:
1, 現要求文件服務器裏有若干個文件,每個文件(假設)只有一種屬性:長度(in bytes)。
當收到stat查詢請求時,獲取參數<pathname>指定的文件長度,並以字符串形式返回給客戶端。
2, 當收到retr下傳請求時,則開始向客戶端寫入<pathname>指定的文件數據。
當上傳下載文件時,沒有對文件進行檢查。
當熱,這樣的程序也只是玩玩,練練手。(厲害的我還不會)
如果有什麼不足,錯誤的,希望大家能夠指出