winsock 完成端口 简单服务器模型

#include "stdafx.h"
#include < Winsock2.h>
#include <malloc.h>
#pragma comment(lib,"Ws2_32.lib")
#define BUFFER_SIZE 1024

void InitSock()
{
 WORD wVersionRequested;
 WSADATA wsaData;
 int err;
 
 wVersionRequested = MAKEWORD( 2, 2 );
 
 err = WSAStartup( wVersionRequested, &wsaData );
 if ( err != 0 ) {
  /* Tell the user that we could not find a usable */
  /* WinSock DLL.                                  */
  return;
 }
 
 /* Confirm that the WinSock DLL supports 2.2.*/
 /* Note that if the DLL supports versions greater    */
 /* than 2.2 in addition to 2.2, it will still return */
 /* 2.2 in wVersion since that is the version we      */
 /* requested.                                        */
 
 if ( LOBYTE( wsaData.wVersion ) != 2 ||
   HIBYTE( wsaData.wVersion ) != 2 ) {
  /* Tell the user that we could not find a usable */
  /* WinSock DLL.                                  */
  WSACleanup( );
  return;
 }

}

typedef struct _BUFFER_OBJ
{
 OVERLAPPED ol;
 char buf[BUFFER_SIZE];
 int nOperatorType;
#define OP_READ 1;
}BUFFER_OBJ,*PBUFFER_OBJ;


typedef struct
{
 SOCKET s;
}SOCKET_OBJ,*PSOCKET_OBJ;

DWORD WINAPI ThreadProc(
  LPVOID lpParameter
)
{
 HANDLE hCompletion = (HANDLE)lpParameter;
 PSOCKET_OBJ pSocket;
 PBUFFER_OBJ pBuffer;
 DWORD dwTrans;
 while(true)
 {
  BOOL ok=::GetQueuedCompletionStatus(hCompletion,&dwTrans,(DWORD *)&pSocket,(LPOVERLAPPED*)&pBuffer,INFINITE);
  if(!ok)
  {
   ::closesocket(pSocket->s);
   ::GlobalFree(pSocket);
   ::GlobalFree(pBuffer);
  }
  else
  {
   if(dwTrans==0)
   {
    printf("close/n");
    ::closesocket(pSocket->s);
    ::GlobalFree(pSocket);
    ::GlobalFree(pBuffer);
   }
   else
   {
    pBuffer->buf[dwTrans]='/0';
    printf("%s/n",pBuffer->buf);
    WSABUF buf;
    buf.buf=pBuffer->buf;
    buf.len=BUFFER_SIZE;
    DWORD dwBytes;
    DWORD dwFlags=0;
    if(SOCKET_ERROR==WSARecv(pSocket->s,&buf,1,&dwBytes,&dwFlags,&pBuffer->ol,NULL))
    {
     if(WSA_IO_PENDING==::WSAGetLastError())
     {
      printf("succ/n");
     }
    }
   }
  }
 }
 return 0;
}
int _tmain(int argc, _TCHAR* argv[])
{
 InitSock();
 HANDLE hCompletion=CreateIoCompletionPort(INVALID_HANDLE_VALUE,NULL,0,0);
 HANDLE hThread=::CreateThread(NULL,0,ThreadProc,hCompletion,0,NULL);
 CloseHandle(hThread);
 SOCKET sListen=socket(AF_INET,SOCK_STREAM,0);
 sockaddr_in addr;
 addr.sin_addr.S_un.S_addr=INADDR_ANY;
 addr.sin_family=AF_INET;
 addr.sin_port=htons(4567);

 bind(sListen,(sockaddr*)&addr,sizeof(addr));
 listen(sListen,5);
 while(true)
 {
  sockaddr_in remote;
  int len=sizeof(sockaddr_in);
  SOCKET client=accept(sListen,(sockaddr*)&remote,&len);
  if(INVALID_SOCKET == client)
  {
   printf("error/n");
  }
  PSOCKET_OBJ pSocket=(PSOCKET_OBJ)GlobalAlloc(GPTR,sizeof(SOCKET_OBJ));
  pSocket->s=client;
  ::CreateIoCompletionPort((HANDLE)client,hCompletion,(DWORD)pSocket,0);

  PBUFFER_OBJ pBuffer=(PBUFFER_OBJ)::GlobalAlloc(GPTR,sizeof(BUFFER_OBJ));
  pBuffer->nOperatorType=OP_READ;
  //pBuffer->ol.hEvent=::WSACreateEvent();
  WSABUF buf;
  buf.buf=pBuffer->buf;
  buf.len=BUFFER_SIZE;
  DWORD dwBytes;
  DWORD dwFlags=0;
  if(SOCKET_ERROR==WSARecv(client,&buf,1,&dwBytes,&dwFlags,&pBuffer->ol,NULL))
  {
   if(WSA_IO_PENDING==::WSAGetLastError())
   {
    printf("succ/n");
   }
  }
 }
 return 0;
}
 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 利用 winsock 编程实现简单 web 服务器的步骤如下: 1. 创建一个 socket,使用 TCP 协议。 2. 绑定 socket 到本地 IP 地址和端口号。 3. 监听 socket,等待客户端连接。 4. 接受客户端连接请求,创建一个新的 socket 与客户端通信。 5. 接收客户端发送的 HTTP 请求。 6. 解析 HTTP 请求,获取请求的文件名和请求方法。 7. 打开请求的文件,读取文件内容。 8. 构造 HTTP 响应,包括响应头和响应体。 9. 发送 HTTP 响应给客户端。 10. 关闭与客户端的连接,等待下一个客户端连接。 以上是利用 winsock 编程实现简单 web 服务器的基本步骤,具体实现还需要考虑一些细节问题,如并发处理、错误处理等。 ### 回答2: Winsock(Windows sockets)是一种基于 Windows 操作系统的网络编程接口,可以方便地通过程序来实现网络通讯的功能。Web服务器就是一种基于 HTTP 协议的网络应用程序,可以接收来自客户端的请求信息,并返回响应信息。 在使用 Winsock 编程实现简单 web 服务器时,需要遵循以下步骤: 1. 创建套接字 使用 Winsock API 函数中的 socket() 函数创建一个套接字,该套接字需要绑定到一个 IP 地址和端口号。 2. 监听端口 调用 Winsock API 函数中的 bind() 函数将套接字绑定到 IP 地址和端口号,并调用 listen() 函数开始监听客户端请求。 3. 等待连接 使用 Winsock API 函数中的 accept() 函数等待客户端连接请求。当有客户端请求连接时,accept() 函数将返回一个新的套接字,服务器可以使用该套接字与客户端进行通讯。 4. 接收请求 使用 recv() 函数接收客户端传来的请求信息,该请求信息必须符合 HTTP 协议格式。 5. 处理请求 当服务器接收到请求信息后,需要进行解析和处理。根据请求中的 URL,可以确定客户端需要访问的资源,服务器可以根据需要读取相应的文件并将文件内容发送给客户端。当然,这个过程中还需要处理错误信息和异常情况。 6. 发送响应 当服务器处理完请求后,需要使用 send() 函数将响应信息发送给客户端。 以上就是使用 Winsock 编程实现简单 web 服务器的基本步骤,当然,在具体实现过程中,还需要考虑如何提高服务器的性能、处理多个客户端等问题。总之,在网络编程领域,Winsock 作为常用的编程接口,可以为程序员们的网络编程工作提供有力支持。 ### 回答3: Web 服务器是一项非常常见并广泛应用的网络技术,对于想要学习网络编程的开发者来说,掌握如何利用winsock编程实现简单的web服务器是非常有必要的。 一般地,web服务器程序主要由两个部分组成:HTTP请求处理和HTTP响应处理。通过利用winsock提供的API接口,可以实现这些处理部分。HTTP请求处理需要解析客户端的HTTP请求头,首先获取请求的网页文件路径信息,然后判断该文件是否存在,若文件存在,则读取文件数据;若文件不存在,则返回404状态码。HTTP响应处理则需要构建HTTP响应头,包括状态行、消息报头和实体内容,将下发给客户端。 以下是一些可能用到的winsock的API接口: 1. socket() 创建socket 2. bind() 绑定IP和端口号 3. listen() 监听连接请求 4. accept() 接受连接请求 5. recv() 接收数据 6. send() 发送数据 7. closesocket() 关闭socket连接 这里提供一个简单Winsock编程实现HTTP协议的web服务器程序示例: #include <stdio.h> #include <stdlib.h> #include <string.h> #include <WinSock2.h> #pragma comment(lib, "ws2_32.lib") // 链接 Winsock2 库 #define MAX_BUF_SIZE 1024 // 缓存区大小 int main() { WSADATA wsaData; int iResult = WSAStartup(MAKEWORD(2,2), &wsaData); // 初始化 Winsock2 if (iResult != 0) { printf("WSAStartup failed! Error code: %d", iResult); return 1; } // 创建 socket SOCKET listenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (listenSocket == INVALID_SOCKET) { printf("Creating socket failed! Error code: %d", WSAGetLastError()); return 1; } // 绑定 IP 地址和端口号 sockaddr_in sockAddr; sockAddr.sin_family = AF_INET; sockAddr.sin_addr.s_addr = htonl(INADDR_ANY); sockAddr.sin_port = htons(80); iResult = bind(listenSocket, (sockaddr*)&sockAddr, sizeof(sockAddr)); if (iResult == SOCKET_ERROR) { printf("Binding socket failed! Error code: %d", WSAGetLastError()); closesocket(listenSocket); return 1; } // 监听连接请求 iResult = listen(listenSocket, SOMAXCONN); if (iResult == SOCKET_ERROR) { printf("Listening socket failed! Error code: %d", WSAGetLastError()); closesocket(listenSocket); return 1; } char buf[MAX_BUF_SIZE]; // 缓存区 while (TRUE) { // 接受连接请求 SOCKADDR_IN addrClient; int iLength = sizeof(SOCKADDR_IN); SOCKET clientSocket = accept(listenSocket, (SOCKADDR*)&addrClient, &iLength); if (clientSocket == INVALID_SOCKET) { printf("Accepting socket failed! Error code: %d", WSAGetLastError()); closesocket(listenSocket); return 1; } // 接收数据 iResult = recv(clientSocket, buf, MAX_BUF_SIZE, NULL); if (iResult == SOCKET_ERROR) { printf("Receiving data failed! Error code: %d", WSAGetLastError()); closesocket(clientSocket); continue; } buf[iResult] = '\0'; // 让接收到的数据末尾为 \0 // HTTP 请求处理,这里解析了 HTTP 请求中 GET 命令 if (strncmp(buf, "GET", 3) == 0) { char* pPath = strchr(buf, '/'); char* pEnd = strchr(pPath, ' '); if (pEnd == NULL) { closesocket(clientSocket); continue; } *pEnd = '\0'; // 文件路径字符串最后以 \0 结束 char pathBuf[MAX_BUF_SIZE]; memset(pathBuf, '\0', MAX_BUF_SIZE); // 初始化 pathBuf // 处理 HTTP 请求中的文件路径信息 if (strcmp(pPath, "/") == 0) { sprintf(pathBuf, "./index.html"); // 指定默认主页为 index.html } else { sprintf(pathBuf, ".%s", pPath); } FILE* pFile = fopen(pathBuf, "rb"); if (pFile == NULL) { // 发送 HTTP 响应的消息报头数据 sprintf(buf, "HTTP/1.1 404 File Not Found\r\n"); send(clientSocket, buf, strlen(buf), NULL); sprintf(buf, "Content-Type:text/html\r\n\r\n"); send(clientSocket, buf, strlen(buf), NULL); // 发送 HTTP 响应的实体内容数据 sprintf(buf, "<html><body><h1>File Not Found</h1></body></html>"); send(clientSocket, buf, strlen(buf), NULL); } else { // 发送 HTTP 响应的消息报头数据 sprintf(buf, "HTTP/1.1 200 OK\r\n"); send(clientSocket, buf, strlen(buf), NULL); sprintf(buf, "Content-Type:text/html\r\n\r\n"); send(clientSocket, buf, strlen(buf), NULL); // 读取文件数据并发送 HTTP 响应的实体内容数据 int iReadLen = 0; do { iReadLen = fread(buf, 1, MAX_BUF_SIZE, pFile); send(clientSocket, buf, iReadLen, NULL); } while (iReadLen == MAX_BUF_SIZE); // 如果已达到文件尾则结束 while 循环 fclose(pFile); } } closesocket(clientSocket); // 关闭 socket 连接 } WSACleanup(); // 清理 Winsock2 return 0; } 以上示例程序是一个确死版本的web服务器,具有非常基本的功能,同时方便学习和实践。为了提高web服务器的性能和功能,可以学习更加多的winsock编程的知识和技巧。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值