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)); }