C Prog - 保持网络服务器不断监听

发布于 2024-10-22 03:23:30 字数 4402 浏览 0 评论 0原文

我正在尝试使用在线教程学习winsock 编程。此示例来自 MSDN 库,但经过修改。我已经编译了它,它似乎只适用于一个请求。处理完单个请求后,服务器退出。我读过可以通过线程处理多个请求并使服务器持久化,但不知道如何做到这一点,并且在互联网上找不到有用的示例。请帮忙。

#undef UNICODE

#define WIN32_LEAN_AND_MEAN

#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdlib.h>
#include <stdio.h>

// Need to link with Ws2_32.lib
#pragma comment (lib, "Ws2_32.lib")
// #pragma comment (lib, "Mswsock.lib")

#define DEFAULT_BUFLEN 4096
#define DEFAULT_PORT "27015"
char recvbuf[DEFAULT_BUFLEN];

void handleBuffer()
{
recvbuf[DEFAULT_BUFLEN-1]='\0';
printf("\n************The server has received the following request***************\n");
printf("%s",recvbuf);
}

int __cdecl main(void)
{
WSADATA wsaData;
SOCKET ListenSocket = INVALID_SOCKET,
       ClientSocket = INVALID_SOCKET;
struct addrinfo *result = NULL,hints;
char* sendbuf = "HTTP/1.0 200 OK\r\nServer: Test\r\nContent-Type: text/HTML\r\n\r\n<html><title>Test Server</title><body><span style=\"color:#2032DC; font-family:arial; font-size:large; position:absolute; left:4%;\">This is test server responding.</span></body></html>";
int iResult, iSendResult;
int recvbuflen = DEFAULT_BUFLEN;
char e;

// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if (iResult != 0) {
    printf("WSAStartup failed with error: %d\n", iResult);
    return 1;
}
else
    printf("\nInitialising winsock...done");

ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
hints.ai_flags = AI_PASSIVE;
printf("\n");

// Resolve the server address and port
iResult = getaddrinfo(NULL, DEFAULT_PORT, &hints, &result);
if ( iResult != 0 ) {
    printf("getaddrinfo failed with error: %d\n", iResult);
    WSACleanup();
    return 1;
}
else
    printf("\nResolving server address...done");
//localhost:27015/
// Create a SOCKET for connecting to server

ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
if (ListenSocket == INVALID_SOCKET) {
    printf("socket failed with error: %ld\n", WSAGetLastError());
    freeaddrinfo(result);
    WSACleanup();
    return 1;
}
else
    printf("\nCreating connection socket...done");

// Setup the TCP listening socket
iResult = bind( ListenSocket, result->ai_addr, (int)result->ai_addrlen);
if (iResult == SOCKET_ERROR) {
    printf("bind failed with error: %d\n", WSAGetLastError());
    freeaddrinfo(result);
    closesocket(ListenSocket);
    WSACleanup();
    return 1;
}
else
    printf("\nCreating listening socket...done");
    printf("\nWaiting for connection... ");

freeaddrinfo(result);

iResult = listen(ListenSocket, SOMAXCONN);

if (iResult == SOCKET_ERROR) {
    printf("listen failed with error: %d\n", WSAGetLastError());
    closesocket(ListenSocket);
    WSACleanup();
    return 1;
}

    // Accept a client socket
    ClientSocket = accept(ListenSocket, NULL, NULL);
    if (ClientSocket == INVALID_SOCKET) {
        printf("accept failed with error: %d\n", WSAGetLastError());
        closesocket(ListenSocket);
        WSACleanup();
        return 1;
    }

    // No longer need server socket
    closesocket(ListenSocket);

    iResult = recv(ClientSocket, recvbuf, recvbuflen,0);
    if (iResult > 0)
    {
        printf("Bytes received: %d\n", iResult);
    }
    else if (iResult == 0)
        printf("Connection closing...\n");
    else
    {
        printf("recv failed with error: %d\n", WSAGetLastError());
        closesocket(ClientSocket);
        WSACleanup();
        return 1;
    }


    iSendResult = send(ClientSocket,sendbuf,(int)strlen(sendbuf), 0 );
        if (iSendResult == SOCKET_ERROR)
        {
            printf("send failed with error: %d\n", WSAGetLastError());
            closesocket(ClientSocket);
            WSACleanup();
            return 1;
        }
    printf("Bytes sent: %d\n", iSendResult);
    handleBuffer();

    // shutdown the connection since we're done
    iResult = shutdown(ClientSocket, SD_SEND);
    if (iResult == SOCKET_ERROR) {
        printf("shutdown failed with error: %d\n", WSAGetLastError());
        closesocket(ClientSocket);
        WSACleanup();
        return 1;
    }
// cleanup
closesocket(ClientSocket);
WSACleanup();
printf("\n\nPress any key to quit.");

getch();
return 0;
}

I am trying to learn winsock programming using online tutorials. This example is from the MSDN library, although modified. I have compiled it and it seems to be working fine for only one request. After handling a single request the server exits. I have read handling multiple request and making the server persistent can be done through threads, but have no idea how do so and no helpful examples found over the internet. Please help.

#undef UNICODE

#define WIN32_LEAN_AND_MEAN

#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdlib.h>
#include <stdio.h>

// Need to link with Ws2_32.lib
#pragma comment (lib, "Ws2_32.lib")
// #pragma comment (lib, "Mswsock.lib")

#define DEFAULT_BUFLEN 4096
#define DEFAULT_PORT "27015"
char recvbuf[DEFAULT_BUFLEN];

void handleBuffer()
{
recvbuf[DEFAULT_BUFLEN-1]='\0';
printf("\n************The server has received the following request***************\n");
printf("%s",recvbuf);
}

int __cdecl main(void)
{
WSADATA wsaData;
SOCKET ListenSocket = INVALID_SOCKET,
       ClientSocket = INVALID_SOCKET;
struct addrinfo *result = NULL,hints;
char* sendbuf = "HTTP/1.0 200 OK\r\nServer: Test\r\nContent-Type: text/HTML\r\n\r\n<html><title>Test Server</title><body><span style=\"color:#2032DC; font-family:arial; font-size:large; position:absolute; left:4%;\">This is test server responding.</span></body></html>";
int iResult, iSendResult;
int recvbuflen = DEFAULT_BUFLEN;
char e;

// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if (iResult != 0) {
    printf("WSAStartup failed with error: %d\n", iResult);
    return 1;
}
else
    printf("\nInitialising winsock...done");

ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
hints.ai_flags = AI_PASSIVE;
printf("\n");

// Resolve the server address and port
iResult = getaddrinfo(NULL, DEFAULT_PORT, &hints, &result);
if ( iResult != 0 ) {
    printf("getaddrinfo failed with error: %d\n", iResult);
    WSACleanup();
    return 1;
}
else
    printf("\nResolving server address...done");
//localhost:27015/
// Create a SOCKET for connecting to server

ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
if (ListenSocket == INVALID_SOCKET) {
    printf("socket failed with error: %ld\n", WSAGetLastError());
    freeaddrinfo(result);
    WSACleanup();
    return 1;
}
else
    printf("\nCreating connection socket...done");

// Setup the TCP listening socket
iResult = bind( ListenSocket, result->ai_addr, (int)result->ai_addrlen);
if (iResult == SOCKET_ERROR) {
    printf("bind failed with error: %d\n", WSAGetLastError());
    freeaddrinfo(result);
    closesocket(ListenSocket);
    WSACleanup();
    return 1;
}
else
    printf("\nCreating listening socket...done");
    printf("\nWaiting for connection... ");

freeaddrinfo(result);

iResult = listen(ListenSocket, SOMAXCONN);

if (iResult == SOCKET_ERROR) {
    printf("listen failed with error: %d\n", WSAGetLastError());
    closesocket(ListenSocket);
    WSACleanup();
    return 1;
}

    // Accept a client socket
    ClientSocket = accept(ListenSocket, NULL, NULL);
    if (ClientSocket == INVALID_SOCKET) {
        printf("accept failed with error: %d\n", WSAGetLastError());
        closesocket(ListenSocket);
        WSACleanup();
        return 1;
    }

    // No longer need server socket
    closesocket(ListenSocket);

    iResult = recv(ClientSocket, recvbuf, recvbuflen,0);
    if (iResult > 0)
    {
        printf("Bytes received: %d\n", iResult);
    }
    else if (iResult == 0)
        printf("Connection closing...\n");
    else
    {
        printf("recv failed with error: %d\n", WSAGetLastError());
        closesocket(ClientSocket);
        WSACleanup();
        return 1;
    }


    iSendResult = send(ClientSocket,sendbuf,(int)strlen(sendbuf), 0 );
        if (iSendResult == SOCKET_ERROR)
        {
            printf("send failed with error: %d\n", WSAGetLastError());
            closesocket(ClientSocket);
            WSACleanup();
            return 1;
        }
    printf("Bytes sent: %d\n", iSendResult);
    handleBuffer();

    // shutdown the connection since we're done
    iResult = shutdown(ClientSocket, SD_SEND);
    if (iResult == SOCKET_ERROR) {
        printf("shutdown failed with error: %d\n", WSAGetLastError());
        closesocket(ClientSocket);
        WSACleanup();
        return 1;
    }
// cleanup
closesocket(ClientSocket);
WSACleanup();
printf("\n\nPress any key to quit.");

getch();
return 0;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

翻身的咸鱼 2024-10-29 03:23:30

很简单。

  ClientSocket = accept(ListenSocket, NULL, NULL);

这将返回用于与连接的客户端通信的套接字,您所要做的就是为此套接字执行读/写循环并将其粘贴到新线程中。
同时,保持主循环在accept()上。

什么是你不明白的?

编辑

假设您要使用 Posix Threads,请看一下这个
http://www.yolinux.com/TUTORIALS/LinuxTutorialPosixThreads.html

掌握这个之后您可能需要更多的功能和灵活性:请查看http://www.lowtek.com/sockets/ select.html

您可以使用 select 来避免使用线程,您可以使用它通过线程分配您的客户端(例如 1..N 个客户端由 1 个线程管理)

备注

等等你的代码中有一个漏洞:

int recvbuflen = DEFAULT_BUFLEN;

然后你在接收中使用它..这很糟糕,这可能会产生溢出,为了解决这个问题,请将你的缓冲区声明为:
字符recvbuf[DEFAULT_BUFLEN + 1];

It's straight forward.

  ClientSocket = accept(ListenSocket, NULL, NULL);

This returns the socket used to communicate with the connected client, all you have to do is do a read/write loop for this socket and stick it into a new Thread.
Meanwhile, keep your main looping on the accept().

What's you don't get?

EDIT

Assuming you're going to use Posix Threads, have a look at this
http://www.yolinux.com/TUTORIALS/LinuxTutorialPosixThreads.html

After mastering this, you might need more power and flexibility: check this out http://www.lowtek.com/sockets/select.html

You can use select to avoid using threads, you can use it to distribute your clients through threads (like 1..N client is/are managed by 1 thread)

Remark

Wait there's a hole in your code:

int recvbuflen = DEFAULT_BUFLEN;

then you use this into the receive.. it's bad, this might produce an overflow, in order to solve this, declare your buffer as:
char recvbuf[DEFAULT_BUFLEN + 1];

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文