user-0 提问: C写Windows服务遇到的问题，求帮助！

回复:
user: user-0
content: 恩恩，明白啦。 谢谢

user: user-1
content: 嗯 主要工作目当问题.你可切换工作目录  在 main 中 int main ( ... )  {        // 切换当前工作目当       // 这样就可以使用相对路径了 	char path[512] = {0}; 	int len = strrchr(argv[0], '\\') - argv[0]; 	memcpy(path, argv[0], len); 	SetCurrentDirectory(path);	    还有的小问题 ------------------------------------------------------- brun = true;   //  增加响应服务的(启动/停止)控制 while (brun)        { //        srv_soc, (struct sockaddr *) &from_addr, &from_len);         acpt_soc = accept(srv_soc,(struct sockaddr *)&from_addr,(int *)&from_len);  if (recv_len <1) /* 接收失败 */         {             closesocket(acpt_soc);             //printf("[Web] Fail to recv, error = %d\n", WSAGetLastError());             //break;   // 把 break 改成 continue . 可防止服务因client意外退出  	   continue;         }

user: user-0
content: OK 问题解决了。  那个index.htm 不能写相对路径...要改成绝对路径。

user: user-0
content: 也不行呀.... 我把全部代码贴出来吧。    // mghttp.cpp : Defines the entry point for the console application. //  #include "stdafx.h" #include <stdio.h> #include <Windows.h> #include <stdlib.h> #include "winsock2.h"     #pragma comment(lib, "ws2_32.lib")  /* WinSock使用的库函数 */  /* 定义常量 */ #define HTTP_DEF_PORT        80     /* 连接的缺省端口 */ #define HTTP_BUF_SIZE      1024     /* 缓冲区的大小 */ #define HTTP_FILENAME_LEN   256     /* 文件名长度 */  /* 定义文件类型对应的 Content-Type */ struct doc_type {     char *suffix; /* 文件后缀 */     char *type;   /* Content-Type */ };  struct doc_type file_type[] =  {     {"html",    "text/html"  }, 	{"txt",    "text/html"  },     {"gif",     "image/gif"  }, 	{"php",      "text/html" },     {"jpeg",    "image/jpeg" },     { NULL,      NULL        } };  char *http_res_hdr_tmpl = "HTTP/1.1 200 OK\r\nServer: Huiyong's Server <0.1>\r\n"     "Accept-Ranges: bytes\r\nContent-Length: %d\r\nConnection: close\r\n"     "Content-Type: %s\r\n\r\n";   /**************************************************************************  *  * 函数功能: 根据文件后缀查找对应的 Content-Type.  *  * 参数说明: [IN] suffix, 文件名后缀;  *  * 返 回 值: 成功返回文件对应的 Content-Type, 失败返回 NULL.  *  **************************************************************************/ char *http_get_type_by_suffix(const char *suffix) {     struct doc_type *type;      for (type = file_type; type->suffix; type++)     {         if (strcmp(type->suffix, suffix) == 0)             return type->type;     }      return NULL; }  /**************************************************************************  *  * 函数功能: 解析请求行, 得到文件名及其后缀. 请求行格式:  *           [GET http://www.baidu.com:8080/index.html HTTP/1.1]  *  * 参数说明: [IN]  buf, 字符串指针数组;  *           [IN]  buflen, buf 的长度;  *           [OUT] file_name, 文件名;  *           [OUT] suffix, 文件名后缀;  *  * 返 回 值: void.  *  **************************************************************************/ void http_parse_request_cmd(char *buf, int buflen, char *file_name, char *suffix) {     int length = 0;     char *begin, *end, *bias;      /* 查找 URL 的开始位置 */     begin = strchr(buf, ' ');     begin += 1;              /* 查找 URL 的结束位置 */     end = strchr(begin, ' ');     *end = 0;      bias = strrchr(begin, '/');     length = end - bias;      /* 找到文件名的开始位置 */     if ((*bias == '/') || (*bias == '\\'))     {         bias++;         length--;     }      /* 得到文件名 */     if (length > 0)     {         memcpy(file_name, bias, length);         file_name[length] = 0;          begin = strchr(file_name, '.');         if (begin)             strcpy(suffix, begin + 1);     } }   /**************************************************************************  *  * 函数功能: 向客户端发送 HTTP 响应.  *  * 参数说明: [IN]  buf, 字符串指针数组;  *           [IN]  buf_len, buf 的长度;  *  * 返 回 值: 成功返回非0, 失败返回0.  *  **************************************************************************/ int http_send_response(SOCKET soc, char *buf, int buf_len) {     int read_len, file_len, hdr_len, send_len;     char *type;     char read_buf[HTTP_BUF_SIZE];     char http_header[HTTP_BUF_SIZE];     char file_name[HTTP_FILENAME_LEN] = "index.html", suffix[16] = "html";     FILE *res_file;      /* 得到文件名和后缀 */     http_parse_request_cmd(buf, buf_len, file_name, suffix);      res_file = fopen(file_name, "rb+"); /* 用二进制格式打开文件 */     if (res_file == NULL)     {         printf("[Web] The file [%s] is not existed\n", file_name);         return 0;     }      fseek(res_file, 0, SEEK_END);     file_len = ftell(res_file);     fseek(res_file, 0, SEEK_SET);          type = http_get_type_by_suffix(suffix); /* 文件对应的 Content-Type */     if (type == NULL)     {         printf("[Web] There is not the related content type\n");         return 0;     }      /* 构造 HTTP 首部，并发送 */     hdr_len = sprintf(http_header, http_res_hdr_tmpl, file_len, type);     send_len = send(soc, http_header, hdr_len, 0);      if (send_len == SOCKET_ERROR)     {         fclose(res_file);         printf("[Web] Fail to send, error = %d\n", WSAGetLastError());         return 0;     }      do /* 发送文件, HTTP 的消息体 */     {         read_len = fread(read_buf, sizeof(char), HTTP_BUF_SIZE, res_file);          if (read_len > 0)         {             send_len = send(soc, read_buf, read_len, 0);             file_len -= read_len;         }     } while ((read_len > 0) && (file_len > 0));      fclose(res_file);          return 1; }   #define SLEEP_TIME 5000 //间隔时间     #define FILE_PATH "C:\\log.txt" //信息输出文件     bool brun=false;     SERVICE_STATUS servicestatus;     SERVICE_STATUS_HANDLE hstatus;           int WriteToLog(char* str);     void WINAPI ServiceMain(int argc, char** argv);     void WINAPI CtrlHandler(DWORD request);     int InitService();           int WriteToLog(char* str)     {   return 0;     }           void WINAPI ServiceMain(int argc, char** argv)     {      servicestatus.dwServiceType = SERVICE_WIN32;     servicestatus.dwCurrentState = SERVICE_START_PENDING;     servicestatus.dwControlsAccepted = SERVICE_ACCEPT_SHUTDOWN|SERVICE_ACCEPT_STOP;//在本例中只接受系统关机和停止服务两种控制命令     servicestatus.dwWin32ExitCode = 0;     servicestatus.dwServiceSpecificExitCode = 0;     servicestatus.dwCheckPoint = 0;     servicestatus.dwWaitHint = 0;     hstatus = ::RegisterServiceCtrlHandler("testservice", CtrlHandler);     if (hstatus==0)     {         WriteToLog("RegisterServiceCtrlHandler failed");         return;     }      //WriteToLog("RegisterServiceCtrlHandler success");      //向SCM 报告运行状态      servicestatus.dwCurrentState = SERVICE_RUNNING;      SetServiceStatus (hstatus, &servicestatus);      //下面就开始任务循环了，你可以添加你自己希望服务做的工作       WSADATA wsa_data;     SOCKET srv_soc = 0, acpt_soc;  /* socket 句柄 */     struct sockaddr_in serv_addr;   /* 服务器地址  */     struct sockaddr_in from_addr;   /* 客户端地址  */     char recv_buf[HTTP_BUF_SIZE];     unsigned short port = HTTP_DEF_PORT;     unsigned long  from_len = sizeof(from_addr);     int result = 0, recv_len;     // if (argc == 2) /* 端口号 */         port = atoi("90");      WSAStartup(MAKEWORD(2,2), &wsa_data); /* 初始化 WinSock 资源 */          srv_soc = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP) ; /* 创建 socket */     if (srv_soc == INVALID_SOCKET)     {         //printf("[Web] socket() Fails, error = %d\n", WSAGetLastError());         return;      }          /* 服务器地址 */     serv_addr.sin_family = AF_INET;     serv_addr.sin_port = htons(port);     serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);      result = bind(srv_soc, (struct sockaddr *) &serv_addr, sizeof(serv_addr));     if (result == SOCKET_ERROR) /* 绑定失败 */     {         closesocket(srv_soc);         //printf("[Web] Fail to bind, error = %d\n", WSAGetLastError());         return;      }      result = listen(srv_soc, SOMAXCONN);     printf("[Web] The server is running ... ...\n");      while (1)     { //		srv_soc, (struct sockaddr *) &from_addr, &from_len);         acpt_soc = accept(srv_soc,(struct sockaddr *)&from_addr,(int *)&from_len);         if (acpt_soc == INVALID_SOCKET) /* 接受失败 */         {             //printf("[Web] Fail to accept, error = %d\n", WSAGetLastError());             break;          }          printf("[Web] Accepted address:[%s], port:[%d]\n",              inet_ntoa(from_addr.sin_addr), ntohs(from_addr.sin_port));          recv_len = recv(acpt_soc, recv_buf, HTTP_BUF_SIZE, 0);         if (recv_len <1) /* 接收失败 */         {             closesocket(acpt_soc);             //printf("[Web] Fail to recv, error = %d\n", WSAGetLastError());             break;          }          recv_buf[recv_len] = 0;          /* 向客户端发送响应数据 */         result = http_send_response(acpt_soc, recv_buf, recv_len);         closesocket(acpt_soc);     }          closesocket(srv_soc);     WSACleanup(); }           void WINAPI CtrlHandler(DWORD request)     {         switch (request)         {             case SERVICE_CONTROL_STOP:                 brun=false;                 servicestatus.dwCurrentState = SERVICE_STOPPED;                 break;             case SERVICE_CONTROL_SHUTDOWN:                 brun=false;                 servicestatus.dwCurrentState = SERVICE_STOPPED;                 break;             default:                 break;         }         SetServiceStatus (hstatus, &servicestatus);           }   int main(int argc, char* argv[])     {         SERVICE_TABLE_ENTRY entrytable[2];         entrytable[0].lpServiceName="testservice";         entrytable[0].lpServiceProc=(LPSERVICE_MAIN_FUNCTION)ServiceMain;         entrytable[1].lpServiceName=NULL;         entrytable[1].lpServiceProc=NULL;         StartServiceCtrlDispatcher(entrytable); 	return 0; }

user: user-1
content: srv_soc = socket(AF_INET, SOCK_STREAM, 0); /* 创建 socket */ 改成: srv_soc = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP) ;

user: user-0
content: 嗯嗯 谢谢，我是在win7下测试的。 windows防火区服务已经关掉了。很奇怪。。。

user: user-1
content: 没看到什么问题 (socket 部份, 我对写win服务不了解)  用telnet 测试下 telnet 127.0.0.1 90  如果连不上，猜有可能是防墙问题    // ------------------------- recv_len = recv(acpt_soc, recv_buf, HTTP_BUF_SIZE, 0);         if (recv_len == SOCKET_ERROR) /* 接收失败 */     << ------ 这个条件改成  recv_len < 1 会好点         {             ...