包含互斥锁 C++ 时的套接字问题

Posted

技术标签:

【中文标题】包含互斥锁 C++ 时的套接字问题【英文标题】:Socket issue when include mutex C++ 【发布时间】:2016-03-27 13:17:10 【问题描述】:

我编写了一个程序,它应该在一个额外的线程中使用一个套接字创建一个服务器。这很好直到#include <mutex> 到我的应用程序。但我需要为另一个函数包含互斥锁(不在此处的示例中)。

当我包含互斥锁时,我在调用bind(代码中标记)时收到此错误:

错误 C2440:“=”:无法在 (PATH_TO_PROJECT_LINE_WHERE_BIND_IS_CALLED) 中将“std::_Bind”转换为“long”

这是我的代码:

#include "stdafx.h"
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#pragma comment(lib,"ws2_32.lib")

#include <cstdio>
#include <WinSock2.h>
#include <iostream>
#include <Windows.h>
#include <string>
#include <process.h>
#include <mutex> //if I do not include mutex, everything works


using namespace std;






unsigned int __stdcall threadCreateServer(void*data)

    long res;

    WSADATA wsaData;

    res = WSAStartup(MAKEWORD(2, 0), &wsaData);
    if (res == 0)
        cout << "[CreateServer] " << "WSAStartup successful" << endl;
    
    else 
        cout << "[CreateServer] " << "Error WSAStartup" << endl;
        return -201;
    

    SOCKET slisten, client;

    slisten = socket(AF_INET, SOCK_STREAM, 0); 
    if (slisten != INVALID_SOCKET)
        cout << "[CreateServer] " << "Socket() successful" << endl;
    
    else
        cout << "[CreateServer] " << "error Socket" << endl;
        return -202;
    


    sockaddr_in info;
    info.sin_addr.s_addr = inet_addr("127.0.0.1");
    info.sin_family = AF_INET;
    info.sin_port = htons(54126);

    res = bind(slisten, (struct sockaddr*)&info, sizeof(info)); //ERROR HERE
    if (res != SOCKET_ERROR)
        cout << "bind successful" << endl;
    
    else 
        cout << "ERROR bind" << endl;
        return -203;
    

    res = listen(slisten, 1); 
    if (res != SOCKET_ERROR)
        cout << "[CreateServer] " << "Listen successful" << endl;
    
    else 
        cout << "[CreateServer] " << "Listen error" << endl;
        return -204;
    
    sockaddr_in clientinfo;
    int clientinfolen = sizeof(clientinfo);

    cout << endl << "~~~~~~~~~" << endl << "[CreateServer] " << "Please connect a client to " << inet_ntoa(info.sin_addr) << ":" << ntohs(info.sin_port) << endl << "~~~~~~~~~" << endl;
    client = accept(slisten, (struct sockaddr*)&clientinfo, &clientinfolen);
    if (client != SOCKET_ERROR)
        cout << "[CreateServer] " << "Client accepted " << inet_ntoa(clientinfo.sin_addr) << ":" << ntohs(clientinfo.sin_port) << endl;
    
    else
        cout << "[CreateServer] " << "ERROR client not accepted" << endl;
    




int _tmain(int argc, _TCHAR* argv[])



    HANDLE handleThreadCreateServer=(HANDLE)_beginthreadex(0,0,&threadCreateServer,0,0,0);

    WaitForSingleObject(handleThreadCreateServer, INFINITE);
    CloseHandle(handleThreadCreateServer);


    return 0;

【问题讨论】:

功能冲突?您是否已经尝试删除 using namespace std; 这行得通。有没有办法使用命名空间但避免这个问题?我的应用程序有 1000 多行代码,因此删除 using namespace std 会很麻烦。 尝试添加using std::string; ... 这就是为什么每个 C++ FAQ 都告诉你不要盲目地从任何命名空间导入东西。我很确定您也可以显式调用 ::bind() 来消除导入符号和全局符号之间的歧义。 使用::bind() 是此示例中需要最少代码更改的正确解决方案。但从长远来看,删除using namespace std 语句将是首选 解决方案。 【参考方案1】:

正如评论中所建议的,我不能做using namespace std,因为包含mutex 时会出现冲突的功能。 对于也会遇到此问题的每个人:

//to not using namespace std, but:
using std::cout;
using std::endl;
using std::string;

对于直到现在未使用的所有其他功能,都必须添加类似的行。不可能使用命名空间 std 和“未使用”std::mutex。

【讨论】:

请注意,您可以限定using 语句。因此,您可以将using namespace std 放在每个不需要互斥锁的函数的开头。最好将互斥锁代码放在一个小的单独的地方,以减少混淆。 谢谢!这是一个伟大的“妥协”

以上是关于包含互斥锁 C++ 时的套接字问题的主要内容,如果未能解决你的问题,请参考以下文章

27 Apr 18 GIL 多进程多线程使用场景 线程互斥锁与GIL对比 基于多线程实现并发的套接字通信 进程池与线程池 同步异步阻塞非阻塞

我是不是需要锁定才能同时使用同一个应用程序两次写入套接字?

来回 unix 域套接字锁

基于JAVA套接字的简单网络聊天程序

Pthread Mutex 挂在一个线程中

boost::asio::socket 线程安全