www.pudn.com > MyFtpServ.rar > main.cpp


/*---------------------------------------------------- 
	MAIN.C -- myFtpServ Program 
			  ZhuJiaJun,2002 
  ----------------------------------------------------*/ 
 
#include  
#include  
#include  
#include  
#include  
#include  
 
#include "command.h" 
#include "const.h" 
#include "resource.h" 
#include "typedef.h" 
#include "util.h" 
#include "ftp.h" 
 
	/* function from util.h */ 
extern void EditPrintf (HWND hwndEdit, TCHAR * szFormat, ...); 
extern int Io_Send(SOCKET sock, char *info, ...); 
extern int Io_Recv(SOCKET sock, char *buf, int size, int min); 
extern void Convert_Str(char *buf); 
extern void bZero_Str(char *buf); 
//从客户端返回的PORT命令的字符串中得到客户的数据端口 
extern short int Get_Port(char *buf); 
 
	/* function from ftp.h */ 
extern void Change_Directory(Client_Socket_Ptr client, char* list); 
extern void Get_Directory(Client_Socket_Ptr client, char* dir); 
 
LRESULT CALLBACK WndProc   (HWND, UINT, WPARAM, LPARAM); 
BOOL    CALLBACK MainDlg   (HWND, UINT, WPARAM, LPARAM); 
 
BOOL Server_Bind(Server_Socket_Ptr tempsock,HWND hwnd); 
void Server_Quit(Server_Socket_Ptr H, Client_Socket_Ptr C); 
int  Server_SendResponse(SOCKET sock, char *ack, char *info, ...); 
 
BOOL Client_DataSocket_Create(Client_Socket_Ptr Client); 
BOOL Client_DataSocket_Transfer(Client_Socket_Ptr Client, char* cmd, char* transfer_file); 
BOOL Client_Transfer_Operation(HWND hwnd, HWND hwndEdit, Client_Socket_Ptr Client, char* cmd, char* transfer_file);  
BOOL Client_DataSocket_FileSend(Client_Socket_Ptr client, char* transfer_file, int size); 
void Client_Quit(Client_Socket_Ptr Client); 
 
HINSTANCE		hInst; 
HWND			hwndModeless; 
 
Server_Socket	Host;				/* 用于监听的socket */ 
Client_Socket	Client[MAX_MEMBER]; /* 用于和用户连接的socket */	 
 
HWND			hwndEdit; 
int				iError;		/* 记录错误信息的值 */ 
char			cbuf[MAX_L_STR];		/* command buffer */ 
 
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, 
                    LPSTR szCmdLine, int nCmdShow) 
{ 
     static TCHAR szAppName[] = TEXT ("myFtpServ") ; 
     HWND         hwnd ; 
     MSG          msg ; 
     RECT         rect ; 
     WNDCLASS     wndclass ; 
 
     hInst = hInstance ; 
 
     wndclass.style         = 0 ; 
     wndclass.lpfnWndProc   = WndProc ; 
     wndclass.cbClsExtra    = 0 ; 
     wndclass.cbWndExtra    = 0 ; 
     wndclass.hInstance     = hInstance ; 
     wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION) ; 
     wndclass.hCursor       = NULL ; 
     wndclass.hbrBackground = NULL ; 
     wndclass.lpszMenuName  = NULL ; 
     wndclass.lpszClassName = szAppName ; 
 
     if (!RegisterClass (&wndclass)) 
     { 
          MessageBox (NULL, TEXT ("This program requires Windows NT!"),  
                      szAppName, MB_ICONERROR) ; 
          return 0 ; 
     } 
      
     hwnd = CreateWindow (szAppName, TEXT ("Set Ftp Server For LAN"), 
                          WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | 
                               WS_BORDER | WS_MINIMIZEBOX, 
                          CW_USEDEFAULT, CW_USEDEFAULT, 
                          CW_USEDEFAULT, CW_USEDEFAULT, 
                          NULL, NULL, hInstance, NULL) ; 
 
          // Create the modeless dialog box to go on top of the window 
 
     hwndModeless = CreateDialog (hInstance, szAppName, hwnd, MainDlg) ; 
 
          // Size the main parent window to the size of the dialog box.   
          //   Show both windows. 
 
     GetWindowRect (hwndModeless, &rect) ; 
     AdjustWindowRect (&rect, WS_CAPTION | WS_BORDER, FALSE) ; 
 
     SetWindowPos (hwnd, NULL, 0, 0, rect.right - rect.left, 
                   rect.bottom - rect.top, SWP_NOMOVE) ; 
 
     ShowWindow (hwndModeless, SW_SHOW) ;      
     ShowWindow (hwnd, nCmdShow) ; 
     UpdateWindow (hwnd) ; 
 
          // Normal message loop when a modeless dialog box is used. 
 
     while (GetMessage (&msg, NULL, 0, 0)) 
     { 
          if (hwndModeless == 0 || !IsDialogMessage (hwndModeless, &msg)) 
          { 
               TranslateMessage (&msg) ; 
               DispatchMessage (&msg) ; 
          } 
     } 
     return msg.wParam ; 
} 
 
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 
{ 
     switch (message) 
     { 
     case WM_SETFOCUS: 
          SetFocus (hwndModeless) ; 
          return 0 ; 
 
     case WM_DESTROY: 
          PostQuitMessage (0) ; 
          return 0 ; 
     } 
     return DefWindowProc (hwnd, message, wParam, lParam) ; 
} 
 
BOOL CALLBACK MainDlg (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 
{ 
    static HWND   hwndButton; 
    static TCHAR  szOKLabel[32]; 
    int           sin_size; 
	char		  *pos, *dir; 
    WORD          wEvent, wError ;    
 
    switch (message) 
    { 
    case WM_INITDIALOG: 
         hwndButton = GetDlgItem (hwnd, IDOK) ; 
         hwndEdit = GetDlgItem (hwnd, IDC_TEXTOUT) ; 
		 return TRUE ; 
 
    case WM_COMMAND: 
		switch (LOWORD (wParam)) 
        { 
        case IDOK: 
 
				/* Server socket create, Bind and listen */ 
			if (!Server_Bind((Server_Socket_Ptr)&Host, hwnd))  
				return TRUE; 
 
				// The result of the "accept" call will be reported  
                // through the WM_SOCKET_NOTIFY message. 
                // Set timer and change the button to "Cancel" 
 
			GetWindowText (hwndButton, szOKLabel, sizeof (szOKLabel)/sizeof (TCHAR)) ; 
            SetWindowText (hwndButton, TEXT ("Cancel")) ; 
            SetWindowLong (hwndButton, GWL_ID, IDCANCEL) ; 
            return TRUE ; 
 
        case IDCANCEL: 
			Server_Quit((Server_Socket_Ptr)&Host, (Client_Socket_Ptr)&Client[0]); 
 
            SetWindowText (hwndButton, szOKLabel) ; 
            SetWindowLong (hwndButton, GWL_ID, IDOK) ; 
 
            EditPrintf (hwndEdit, TEXT ("\r\nSocket closed.\r\n")) ; 
            return TRUE ; 
 
        case IDC_CLOSE: 
			if (Host.sock) 
				SendMessage (hwnd, WM_COMMAND, IDCANCEL, 0) ; 
 
            DestroyWindow (GetParent (hwnd)) ; 
            return TRUE ; 
		case IDC_SENDMSG: 
			return TRUE; 
        } 
        return FALSE ; 
 
     case WM_SOCKET_NOTIFY: 
 
          wEvent = WSAGETSELECTEVENT (lParam) ;   // ie, LOWORD 
          wError = WSAGETSELECTERROR (lParam) ;   // ie, HIWORD 
               // Process two events specified in WSAAsyncSelect 
          switch (wEvent) 
          { 
               // This event occurs as a result of the "connect" call 
          case FD_ACCEPT: 
					//不允许更多的用户访问 
			   if (Host.clientcount == 1)  
					return TRUE; 
					/*调用"accept"函数*/ 
			   sin_size = sizeof(SOCKADDR); 
			   Client[0].sock = accept(wParam, (SOCKADDR *)&Client[0].ca, &sin_size); 
			   if (Client[0].sock == INVALID_SOCKET) 
			   { 
					EditPrintf (hwndEdit, TEXT ("accept error #%i.\r\n"),  
						        WSAGetLastError()) ; 
					closesocket (Host.sock) ; 
					WSACleanup () ; 
					return TRUE ; 
				 
			   } 
			   Host.clientcount++; 
			   EditPrintf (hwndEdit, TEXT ("Waiting For Connect ...")); 
			   EditPrintf (hwndEdit, TEXT ("\r\n")) ; 
               if (wError) 
               { 
                    EditPrintf (hwndEdit, TEXT ("Accept error #%i."),  
                                wError) ; 
                    SendMessage (hwnd, WM_COMMAND, IDCANCEL, 0) ; 
                    return TRUE ; 
               } 
               EditPrintf (hwndEdit, TEXT ("Connected to %hs.\r\n"), inet_ntoa(Client[0].ca.sin_addr)) ; 
 
			   iError = Server_SendResponse(Client[0].sock, R_220, "myFtpServ For Windows Ready. "); 
			   if (iError == SOCKET_ERROR && WSAGetLastError() != WSAEWOULDBLOCK) 
			   { 
					EditPrintf (hwndEdit,TEXT ("SendResponse error #%i.\r\n"), 
								iError) ; 
                    SendMessage (hwnd, WM_COMMAND, IDCANCEL, 0) ; 
					return TRUE;				 
			   } 
			   EditPrintf (hwndEdit, TEXT ("Send successful: %s %s\r\n"),  
						   R_220, "myFtpServ For Windows Ready.");	 
  
               EditPrintf (hwndEdit, TEXT ("Waiting to receive...")) ; 
					//Client_Socket中的一些常量的初始化在这里完成 
 
					//初始化当前目录为根目录,current_dir[0]用来记录添加的目录数 
			   strset(Client[0].current_dir[0], 0); 
			   strcpy(Client[0].current_dir[0], "0"); 
 
               return TRUE ; 
 
                    // This even occurs when the "recv" call can be made 
		  case FD_READ: 
 
			  if (wError) 
               { 
                    EditPrintf (hwndEdit, TEXT ("FD_READ error #%i."),  
                                wError) ; 
                    SendMessage (hwnd, WM_COMMAND, IDCANCEL, 0) ; 
                    return TRUE ; 
               } 
			 
			   strset(cbuf, 0); 
			   pos = NULL; 
 
                    //调用"recv()函数" 
			   iError = Io_Recv(Client[0].sock,&cbuf[0],MAX_L_STR,0); 
			   if (iError == SOCKET_ERROR && WSAGetLastError() != WSAEWOULDBLOCK) 
			   { 
					EditPrintf (hwndEdit,TEXT ("RecvCommand error #%i.\r\n"), 
								iError) ; 
                    SendMessage (hwnd, WM_COMMAND, IDCANCEL, 0) ; 
					return TRUE;				 
			   } 
			   EditPrintf (hwndEdit, TEXT ("Recv successful: %s\r\n"), cbuf); 
 
			   pos = strstr(cbuf,C_USER); 
			   if (pos == cbuf)  
			   { 
					strncpy(Client[0].user, &cbuf[5],9); 
					if (strcmp(&Client[0].user[0], "anonymous") == 0)  
					{ 
						Server_SendResponse(Client[0].sock, R_331, 
											"Anonymous username allowed, send password."); 
						EditPrintf (hwndEdit, TEXT ("Send successful: %s\r\n"), R_331); 
						return TRUE; 
					} 
					else 
					{ 
						Server_SendResponse(Client[0].sock, R_421, 
											"Username do not allowed, Service is about to be shutdown."); 
						EditPrintf (hwndEdit, TEXT ("Send successful: %s\r\n"), R_421); 
						Client_Quit((Client_Socket_Ptr)&Client[0]);		 
						return TRUE;				 
					} 
			   } 
 
			   pos = strstr(cbuf,C_PASS); 
			   if (pos == cbuf) 
			   { 
					strcpy(Client[0].password,&cbuf[5]); 
					Convert_Str(Client[0].password); 
					Server_SendResponse(Client[0].sock, "230-", 
										"Welcome come to my world!"); 
					Server_SendResponse(Client[0].sock, "230-", 
										"本ftp_server仍然处在测试阶段!"); 
					Server_SendResponse(Client[0].sock, "230-", 
										"您现在可以安全下载较小的文件和文件夹了!"); 
					Server_SendResponse(Client[0].sock, "230-", 
										"在下载很大的文件时,如果出现问题,"); 
					Server_SendResponse(Client[0].sock, "230-", 
										"还望您谅解!"); 
					Server_SendResponse(Client[0].sock, "230-", 
										"欢迎您与我联系:zhujiajun2000@zju.edu.cn"); 
 
					Server_SendResponse(Client[0].sock, R_230, 
										"%s users logged in.", Client[0].user); 
					EditPrintf(hwndEdit, TEXT("Send successful: %s\r\n"), R_230); 
					return TRUE; 
			   } 
 
			   pos = strstr(cbuf,C_SYST); 
			   if (pos == cbuf)  
			   { 
					Server_SendResponse(Client[0].sock, R_215,  
										 "UNIX Type: L8"); 
					EditPrintf(hwndEdit, TEXT("Send successful: %s\r\n"), R_215); 
					return TRUE; 
										  
			   } 
 
			   pos = strstr(cbuf, C_REST); 
			   if (pos == cbuf)  
			   { 
					Server_SendResponse(Client[0].sock, R_350, 
										"Requested file action pending further info."); 
					EditPrintf(hwndEdit, TEXT("Send successful: %s\r\n"), R_350); 
					return TRUE;  
			   } 
 
			   pos = strstr(cbuf, C_PWD); 
			   if (pos == cbuf)  
			   { 
					sin_size = atoi(Client[0].current_dir[0]); 
					dir = (char*)malloc((sin_size+1)*100*sizeof(char));  
					Get_Directory((Client_Socket_Ptr)&Client[0], dir); 
 
					Server_SendResponse(Client[0].sock, R_257, "\"%s\" is current directory.", dir); 
					free(dir); 
					EditPrintf(hwndEdit, TEXT("Send successful: %s\r\n"), R_257); 
					return TRUE;	 
			   }		    
 
			   pos = strstr(cbuf, C_TYPE); 
			   if (pos == cbuf) 
			   { 
					switch (cbuf[5]) 
					{ 
					case 'A': 
						Client[0].type = 'A'; 
						Server_SendResponse(Client[0].sock, R_200, 
											"Type set to A."); 
						EditPrintf(hwndEdit, TEXT("Send successful: %s\r\n"), R_200); 
						return TRUE; 
					case 'I': 
						Client[0].type = 'I'; 
						Server_SendResponse(Client[0].sock, R_200, 
											"Type set to I."); 
						EditPrintf(hwndEdit, TEXT("Send successful: %s\r\n"), R_200); 
						return TRUE;	 
					default : 
						Server_SendResponse(Client[0].sock,R_421, 
											"Username do not allowed, Service is about to be shutdown."); 
						EditPrintf (hwndEdit, TEXT ("Send successful: %s\r\n"), R_421); 
						Client_Quit((Client_Socket_Ptr)&Client[0]); 
						return TRUE; 
					}				 
			   } 
 
			   pos = strstr(cbuf, C_PORT); 
			   if (pos == cbuf) 
			   { 
					Client[0].data.da = Client[0].ca; 
					Client[0].data.da.sin_port = htons(Get_Port(cbuf)); 
					Server_SendResponse(Client[0].sock, R_220, 
										"PORT Command successful."); 
					EditPrintf(hwndEdit, TEXT("Send successful: %s\r\n"), R_220); 
					return TRUE; 
			   } 
 
			   pos = strstr(cbuf, C_LIST); 
			   if (pos == cbuf) 
			   { 
					Client_Transfer_Operation(hwnd, hwndEdit, (Client_Socket_Ptr)&Client[0], C_LIST, NULL); 
					return TRUE; 
			   } 
 
			   pos = strstr(cbuf, C_CWD); 
			   if (pos == cbuf) 
			   { 
/* 
	!!!!!!!!!!!!!!!!!! 
	应该先检查传回的目录名是不是真的在当前目录列表中 
*/ 
					Change_Directory((Client_Socket_Ptr)&Client[0], &cbuf[4]); 
					sin_size = atoi(Client[0].current_dir[0]); 
					dir = (char*)malloc((sin_size+1)*100*sizeof(char)); 
					Get_Directory((Client_Socket_Ptr)&Client[0], dir); 
 
					Server_SendResponse(Client[0].sock, R_250, "Directory changed to %s", dir); 
					EditPrintf(hwndEdit, TEXT("Send successful: %s\r\n"), R_250); 
					free(dir); 
					return TRUE; 
			   } 
 
			   pos = strstr(cbuf, C_CDUP); 
			   if (pos == cbuf) 
			   { 
					sin_size = atoi(Client[0].current_dir[0]); 
					if (sin_size > 0) 
					{ 
						strset(Client[0].current_dir[sin_size], 0); 
						sin_size--; 
						strset(Client[0].current_dir[0], 0); 
						itoa(sin_size, Client[0].current_dir[0], 10); 
					} 
 
					dir = (char*)malloc((sin_size+1)*100*sizeof(char)); 
					Get_Directory((Client_Socket_Ptr)&Client[0], dir); 
 
					Server_SendResponse(Client[0].sock, R_250, "Directory changed to %s", dir); 
					EditPrintf(hwndEdit, TEXT("Send successful: %s\r\n"), R_250); 
					free(dir); 
					return TRUE; 
			   } 
				 
			   pos = strstr(cbuf, C_NOOP); 
			   if (pos == cbuf) 
			   { 
					Server_SendResponse(Client[0].sock, R_200, "Command okay."); 	 
					EditPrintf(hwndEdit, TEXT("Send successful: %s\r\n"), R_200); 
					return TRUE; 
			   } 
 
			   pos = strstr(cbuf, C_RETR); 
			   if (pos == cbuf) 
			   { 
					dir = (char*)malloc(255*sizeof(char)); 
					strcpy(dir, &cbuf[5]); 
					Convert_Str(dir); 
					Client_Transfer_Operation(hwnd, hwndEdit, (Client_Socket_Ptr)&Client[0], C_RETR, dir); 
					free(dir); 
					return TRUE; 
			   } 
 
			   pos = strstr(cbuf, C_QUIT); 
			   if (pos == cbuf) 
			   { 
					Client_Quit((Client_Socket_Ptr)&Client[0]); 
					return TRUE;		 
			   } 
               return TRUE ;  
		  } 
          return FALSE ; 
	 } 
     return FALSE ; 
} 
 
BOOL Client_DataSocket_Create(Client_Socket_Ptr Client) 
{ 
	int on = 1; 
	int tos = 0; 
 
	Client->data.sock = socket (AF_INET, SOCK_STREAM, IPPROTO_IP); 
 
	if (Client->data.sock == INVALID_SOCKET) 
	{ 
		EditPrintf (hwndEdit,TEXT ("Data Socket creation error for Client[%i] at #%i.\r\n"),  
					0, WSAGetLastError ()) ; 
		return FALSE; 
	} 
	EditPrintf (hwndEdit, TEXT ("Data Socket For Client[%i] at %i created.\r\n"), 
				0, Client->data.sock ) ; 
 
	setsockopt(Client->data.sock, SOL_SOCKET, SO_REUSEADDR, (char*)&on, sizeof(on)); 
/*	#ifdef IPTOS_LOWDELAY 
		tos = IPTOS_LOWDELAY; 
	#endif 
				*/ 
	#ifdef IPTOS_THROUGHPUT 
	    tos |= IPTOS_THROUGHPUT; 
	#endif 
 
	#ifdef IP_TOS 
		if(Client->data.sock != -1) 
		setsockopt(Client->data.sock,IPPROTO_IP,IP_TOS,(void*)&tos,sizeof(tos)); 
	#endif 
 
	return TRUE; 
} 
 
BOOL Client_DataSocket_Transfer(Client_Socket_Ptr Client, char* cmd, char* transfer_file) 
{ 
	int				index,count,send_bytes,i; 
	char			buf[255]; 
	char			*s[100]; 
	WIN32_FIND_DATA file; 
	HANDLE			filehandle; 
	if (Client->data.sock)  
	{ 
		Client->event = WSACreateEvent(); 
 
		WSAEventSelect(Client->data.sock, Client->event,FD_CONNECT); 
		EditPrintf(hwndEdit, TEXT(" An Event For Data Socket of Client[%i] Created.\r\n"), 0); 
				 
		connect(Client->data.sock, (SOCKADDR *)&Client->data.da, sizeof(Client->data.da)); 
 
		index = WSAWaitForMultipleEvents(1,&Client->event, FALSE, WSA_INFINITE, FALSE);  
		WSAEnumNetworkEvents(Client->data.sock, Client->event, &Client->networkevents); 
 
		if (Client->networkevents.lNetworkEvents & FD_CONNECT) 
		{ 
			if (Client->networkevents.iErrorCode[FD_CONNECT_BIT] != 0)  
			{ 
				WSACloseEvent(Client->event); 
				EditPrintf(hwndEdit, TEXT(" Client[%i] Data Socket Connect Error at %i.\r\n"), 
						   0, Client->networkevents.iErrorCode[FD_READ_BIT]); 
				return FALSE; 
			}		 
			if (strcmp(cmd, C_LIST) == 0)  
				Server_SendResponse(Client->sock, R_150,  
									"Open ASCII mode data connection for /bin/ls."); 
			if (strcmp(cmd, C_RETR) == 0)  
			{ 
				Set_Directory(Client); 
				if (!Client_DataSocket_FileSend(Client, transfer_file, 1024)) 
				{ 
					WSACloseEvent(Client->event); 
					return FALSE; 
				} 
			} 
 
			if (strcmp(cmd, C_LIST) == 0) 
			{ 
				Set_Directory(Client); 
				filehandle = FindFirstFile("*.*", &file); 
 
				index = count = send_bytes = i = 0; 
				do { 
					strset(buf, 0); 
					PutFile_ToList(Client, buf, file); 
					if (index != 0) 
						i = strlen(s[index-1])+strlen(buf)+5;	 
					if ( ( (count%10) == 0 ) || ( i  >= 1024 )) 
					{ 
						s[index] = (char*)malloc(1024*(index+1)*sizeof(char)); 
						//注:strset最好不要乱用,用了以后list和s将无法delete		 
						//strset(s[index-1], 0); 
						if (index != 0)  
						{ 
							strcpy(s[index], s[index-1]); 
							free(s[index-1]); 
						} 
						index++; 
					} 
					if (count == 0) 
						strcpy(s[index-1], buf); 
					else 
						strcat(s[index-1], buf); 
					strcat(s[index-1], "\r\n"); 
					FindNextFile(filehandle, &file); 
					count++; 
					if (index >= 100) 
						break; 
				} while(GetLastError() != ERROR_NO_MORE_FILES); 
				 
				count = strlen(s[index-1]);	 
				i = 0; 
				while (count > 0)  
				{ 
					send_bytes = send(Client->data.sock, s[index-1]+i, count, 0); 
					count -= send_bytes; 
					i += send_bytes; 
				} 
				free(s[index-1]); 
			} 
		}	 
		WSACloseEvent(Client->event); 
		return TRUE; 
	}				 
	else 
		return FALSE;	 
} 
 
BOOL Client_DataSocket_FileSend(Client_Socket_Ptr client, char* transfer_file, int size) 
{ 
	WIN32_FIND_DATA file; 
	HANDLE			filehandle; 
	FILE			*stream; 
	byte			*list,*ptr,*s; 
	register unsigned int	i, send_bytes; 
	unsigned int	t, num, count, k, addi; 
	char            *a; 
 
	if ((filehandle = FindFirstFile(transfer_file, &file)) == INVALID_HANDLE_VALUE) 
		return FALSE; 
	switch (client->type) 
	{ 
	case 'A': 
		num = t = 0; 
		list = ptr = s = NULL; 
		if ( (stream = fopen(transfer_file, "r")) != NULL) 
		{ 
			Server_SendResponse(Client->sock, R_150, 
					"Open ASCII mode data connection for %s(%d bytes).", transfer_file, file.nFileSizeLow); 
			s = new byte[1024]; 
			list = new byte[1024]; 
			do { 
				ptr = list;	 
				//注:strset最好不要乱用,用了以后list和s将无法delete		 
//				strset(s, 0); 
//				strset(ptr, 0); 
				fseek(stream, t, 0); 
				num = fread(s, sizeof(byte), (size/2), stream); 
				addi = 0; 
				for (i = 0; i < num; i++) 
				{ 
					if (*(s+i) == '\n') 
					{ 
						*(ptr++) = '\r'; 
						*(ptr++) = '\n'; 
						addi++;					  
					} 
					else 
						*(ptr++) = *(s+i); 
				} 
				count = num+addi; 
				//count = num; 
				i = send_bytes = 0; 
				ptr = list; 
				while( count > 0) 
				{ 
					send_bytes = send(client->data.sock, (const char*)ptr+i, count, 0); 
					if(send_bytes==SOCKET_ERROR) 
					{ 
						num = -1; 
						break; 
					} 
					else if(send_bytes==0) 
						break; 
					count -= send_bytes; 
					i += send_bytes; 
				} 
				t += num; 
			} while ((num > 0) || (t < file.nFileSizeLow)); 
			delete list; 
			delete s; 
			fclose(stream); 
			return TRUE;		 
		} 
	case 'I': 
		num = t = 0; 
		list = NULL; 
		k = 0; 
		if ( (stream = fopen(transfer_file, "rb")) != NULL) 
		{ 
 
			Server_SendResponse(Client->sock, R_150, 
					"Opening BINARY mode data connection for %s(%d bytes).", transfer_file, file.nFileSizeLow); 
 
/*			while ( (num = fread(buf, 1, sizeof(buf), stream)) > 0) 
			{ 
				count = num; 
				i = send_bytes = 0; 
				while( count > 0) 
				{ 
					send_bytes = send(client->data.sock, buf+i, count, 0); 
					count -= send_bytes; 
					i += send_bytes; 
				} 
				EditPrintf(hwndEdit, "%d\r\n", num);	 
			} 
			fclose(stream); 
			return TRUE;   */ 
			a = new char[8192]; 
			do { 
				fseek(stream, t, 0); 
				num = fread(a, sizeof(char), 8192, stream); 
				if (ferror(stream)) 
				{ 
					MessageBeep(MB_ICONQUESTION); 
					EditPrintf(hwndEdit, "error file!"); 
					break; 
				} 
				if (num > 0) 
				{ 
					do { 
						send_bytes = send(client->data.sock, (const char*)a, num, 0); 
						if(send_bytes==SOCKET_ERROR) 
						{ 
							MessageBeep(MB_ICONQUESTION); 
							EditPrintf(hwndEdit, "error socket!"); 
						} 
					} while(send_bytes == SOCKET_ERROR); 
				} 
				if (num < 8192) 
					EditPrintf(hwndEdit, "%d, ", num); 
				t += num; 
 
				/*count = num; 
				i = send_bytes = 0; 
				while( count > 0) 
				{ 
					send_bytes = send(client->data.sock, (const char*)list, count, 0); 
					if(send_bytes==SOCKET_ERROR) 
					{ 
						num = -1; 
						break; 
					} 
					else if(send_bytes==0) 
						break; 
					count -= send_bytes; 
					i += send_bytes; 
				} 
				t += num;*/ 
			} while ((num > 0) || (t < file.nFileSizeLow));  
			closesocket(client->data.sock); 
			delete list; 
			fclose(stream); 
			return TRUE;  
		} 
	} 
	return TRUE; 
} 
 
 
BOOL Client_Transfer_Operation(HWND hwnd, HWND hwndEdit, Client_Socket_Ptr Client,char* cmd, char* transfer_file)  
{ 
	if (!Client_DataSocket_Create(Client)) 
	{ 
		Client_Quit((Client_Socket_Ptr)&Client[0]); 
		return FALSE; 
	} 
 
	if (!Client_DataSocket_Transfer(Client, cmd, transfer_file)) 
	{ 
		Client_Quit((Client_Socket_Ptr)&Client[0]);		 
		return FALSE; 
	} 
	else 
	{ 
		closesocket(Client->data.sock); 
		Server_SendResponse(Client->sock, R_226, "Transfer commplete."); 
		EditPrintf(hwndEdit, TEXT("Send successful: %s\r\n"), R_226); 
	} 
	return TRUE; 
} 
 
void Client_Quit(Client_Socket_Ptr Client) 
{ 
	closesocket(Client[0].data.sock); 
	Server_SendResponse(Client[0].sock, R_221, "Service closing control connection, as per normal."); 	 
	EditPrintf(hwndEdit, TEXT("Send successful: %s\r\n"), R_221); 
	closesocket(Client[0].sock); 
	Host.clientcount--; 
} 
 
BOOL Server_Bind(Server_Socket_Ptr	tempsock, HWND hwnd) 
{ 
	WSADATA		  WSAData; 
	int 		  on = 1; 
 
	tempsock->clientcount = 0; 
 
		// Call "WSAStartup" and display description text 
	if (iError = WSAStartup (MAKEWORD(2,0), &WSAData)) 
	{ 
		EditPrintf (hwndEdit, TEXT ("Startup error #%i.\r\n"),  
					iError) ; 
		return FALSE; 
	} 
	EditPrintf (hwndEdit, TEXT ("Started up %hs\r\n"),  
				WSAData.szDescription); 
 
		// Call "socket" 
	tempsock->sock = socket (AF_INET, SOCK_STREAM, IPPROTO_IP) ; 
 
	if (tempsock->sock == INVALID_SOCKET) 
	{ 
		EditPrintf (hwndEdit,TEXT ("Socket creation error #%i.\r\n"),  
					WSAGetLastError ()) ; 
		WSACleanup () ; 
		return FALSE ; 
	} 
	EditPrintf (hwndEdit, TEXT ("Socket %i created.\r\n"), tempsock->sock) ; 
 
//	on = setsockopt(tempsock->sock, SOL_SOCKET, SO_REUSEADDR, (void*)&on, sizeof(on)); 
    setsockopt(tempsock->sock,IPPROTO_TCP,TCP_NODELAY,(char*)&on,sizeof(on)); 
 
		// Call "WSAAsyncSelect"  
	if (SOCKET_ERROR == WSAAsyncSelect (tempsock->sock, hwnd, WM_SOCKET_NOTIFY, FD_ACCEPT | FD_READ)) 
	{ 
		EditPrintf (hwndEdit,TEXT ("WSAAsyncSelect error #%i.\r\n"), 
					WSAGetLastError ()) ; 
		closesocket (tempsock->sock) ; 
		WSACleanup () ; 
		return FALSE ; 
	} 
	tempsock->hwnd = hwnd; 
 
		/*调用"bind"函数 */ 
	tempsock->sa.sin_family			  = AF_INET ; 
	tempsock->sa.sin_port			  = htons(FTP_PORT); 
    tempsock->sa.sin_addr.s_addr = htonl(INADDR_ANY); 
	iError = bind(tempsock->sock, (SOCKADDR *)&tempsock->sa, sizeof(tempsock->sa)); 
    if (iError == SOCKET_ERROR && WSAGetLastError() != WSAEADDRINUSE) 
	{ 
		EditPrintf (hwndEdit,TEXT ("bind error at #%i,port conflict.\r\n"), 
                    WSAGetLastError ()) ; 
        closesocket (tempsock->sock) ; 
		WSACleanup () ; 
		return FALSE ;				 
	} 
	EditPrintf(hwndEdit, TEXT ("bind successful\r\n")); 
 
		/*调用"listen"函数 */ 
	listen(tempsock->sock,1); 
	EditPrintf(hwndEdit, TEXT ("listen successful\r\n")); 
 
	return TRUE; 
} 
 
void Server_Quit(Server_Socket_Ptr H, Client_Socket_Ptr C) 
{ 
	closesocket (H->sock) ; 
	H->sock = 0 ; 
 
	closesocket (C->sock); 
	C->sock = 0; 	 
 
	closesocket (C->data.sock); 
	C->data.sock = 0; 
 
    WSACleanup () ; 
} 
 
int Server_SendResponse(SOCKET sock, char *resp_numeric, char *info, ...) 
{ 
	char		sbuf[MAX_L_STR]; 
	va_list		msg; 
 
	va_start(msg,info); 
	wvsprintf(sbuf, info, msg); 
	va_end(msg); 
   
	sbuf[sizeof(sbuf) - 1] = '\0'; 
 
	return (Io_Send(sock,"%s %s\r\n",resp_numeric, sbuf)); 
}