重用套接字与WinSocket客户端/服务器应用程序

时间:2015-05-13 15:20:22

标签: c++ c windows sockets

我有2个简单的应用程序,一个客户端和一个服务器。客户端连接到服务器,服务器将数据发送到客户端。在客户端应用程序的主循环中,每次我想要接收另一条信息时,我都会关闭套接字并创建一个新套接字。它有效,但它看起来不对我。这是正确的吗?我是否真的需要每次都关闭并重新打开一个套接字,还是有其他方法可以做到这一点?

客户端:

    int main(){
    DWORD id;
    SOCKET s;
    struct sockaddr_in sa;
    WSADATA wsas;
    WORD wersja;
    int recv_size;
    LPTHREAD_START_ROUTINE WINAPI funkcja = getCommend;

    watek = CreateThread(NULL, 0, funkcja, 0, 0, &id);



    wersja = MAKEWORD(2, 0);
    WSAStartup(wersja, &wsas);


    memset((void *)(&sa), 0, sizeof(sa));
    sa.sin_family = AF_INET;
    sa.sin_port = htons(PORT);
    sa.sin_addr.s_addr = inet_addr("25.62.229.110");

    int result;
    s = socket(AF_INET, SOCK_STREAM, 0);
    result = connect(s, (struct sockaddr FAR *) &sa, sizeof(sa));
    if (result == SOCKET_ERROR)
    {
        printf("\nBłąd połączenia!");
        return 1;
    }

    int a;
    if ((recv_size = recv(s, server_reply, SIZE, 0)) == SOCKET_ERROR)
    {
        printf("recv failed\n");
    }
    else{
        while (result != SOCKET_ERROR){
            //printf("%s\n", server_reply);     
            closesocket(s);
            Sleep(1000);
            s = socket(AF_INET, SOCK_STREAM, 0);
            result = connect(s, (struct sockaddr FAR *) &sa, sizeof(sa));
            if (result == SOCKET_ERROR){
                break;
            }
            result = recv_size = recv(s, server_reply, SIZE, 0);
        }
    }
    getchar();
    closesocket(s);
    TerminateThread(watek, NULL);
    WSACleanup();
    return 1;
}

服务器:

int main(){
DWORD id;
SOCKET s, new_socket;
LPTHREAD_START_ROUTINE WINAPI funkcja = getCommend;
struct sockaddr_in sa, sc;
WSADATA wsas;
int c;
watek = CreateThread(NULL,0,funkcja,0,0,&id);

WSAStartup(MAKEWORD(1, 1), &wsas);

s = socket(AF_INET, SOCK_STREAM, 0);

//memset((void *)(&sa), 0, sizeof(sa));
sa.sin_family = AF_INET;
sa.sin_port = htons(PORT);
sa.sin_addr.s_addr = htonl(INADDR_ANY);
bind(s, (struct sockaddr FAR*)&sa, sizeof(sa));
listen(s, 5);
puts("Czekam na polaczenie...");
c = sizeof(struct sockaddr_in);
while ((new_socket = accept(s, (struct sockaddr *)&sc, &c)) != INVALID_SOCKET)
{
    //puts("polaczenie zaakceptowane");
    send(new_socket, message, strlen(message), 0);
}
if (new_socket == INVALID_SOCKET)
{
    printf("Nie udane połaczenie, blad nr : %d", WSAGetLastError());
    return 1;
}
TerminateThread(watek, NULL);   
getchar();
}

2 个答案:

答案 0 :(得分:1)

好吧,这里的一些事情并不常见。

首先,您通常用英语命名变量,而不是用拉丁字母书写的其他语言。我可能会为此付出代价,但这是常见的做法。

第二,我倾向于使用C ++标准而不是OS特定的API。 为什么不使用std::thread而不是WinApi线程?它更加简单,简洁,优雅。

第三,你的代码是100%程序。你没有标准的C ++套接字类,但这并不意味着你不能(或者不应该)编写自己的Socket类,它以优雅的方式处理创建,绑定,发送和接收功能。

第四,即使MSDN示例如此,s也不是变量的好名称。 acceptingSocket可能是。

关于你的实际问题: 你有很多选择,我能想到的3: 1)不要关闭插座并继续接收while循环内的数据 专业人士:易于编写。当服务器有新数据时,客户端立即得到它。 缺点:当您的服务器每次都有少量连接时,这不是一个好方法,因为它会崩溃。

2)让服务器打包数据。然后客户端以预定义的间隔打开一个连接,立即询问所有累积的数据并接收它 专业人士:三者中节省的CPU资源最多 选项。 缺点:您的客户不会立即获得数据,而是以预定义的间隔

3)让客户端在每个会话开始时将本地IP和端口发送到服务器。然后让客户端在本地主机上保持有限的套接字等待连接。每次服务器都有新的东西告诉客户端 - 它只需使用保存的IP和端口连接到客户端,发送数据并关闭连接。然后客户端返回以等待新连接。这样一来 专业人士:在这种情况下,服务器每次都会有尽可能少的连接,如果您希望服务器为许多客户端提供服务,那将是一件好事。 缺点:重量实际上落在客户身上,在许多情况下这不是最好的事情。

答案 1 :(得分:1)

通常的单连接方法是:

Create socket
bind socket
Listen on socket
newsocket = accept on socket
while no accept errors
    while newsocket connected and error free
        process newsocket
    newsocket = accept on socket

多个连接可以通过多种方式处理。

多线程:

create thread pool
Create socket
bind socket
Listen on socket
while no errors
    newsocket = accept on socket
    hand newsocket off to thread pool for processing

Monothread select基于

Create socket
bind socket
Listen on socket
add socket to readFD  list
while no errors
    select on readFD list
    if socket selected
        newsocket = accept on socket
        add newsocket to readFD  list
    while other sockets selected
        process other sockets