C++网络编程

一些网络编程方面的知识,主要是socket的创建、网络连接方面的知识。以便了解和学习使用。

1、加载头文件和库文件

#include <windows.h>
#pragma comment(lib, "ws2_32.lib")

2、服务器端socket的建立、绑定以及监听

WSADATA wsa;//WSADATA结构被用来保存函数WSAStartup返回的Windows Sockets初始化信息

// 加载winsock库并确定winsock版本,系统会把数据填入wsaData中  
if(WSAStartup(MAKEWORD(2,2),&wsa)!=0){
    MessageBoxA(NULL, "套接字初始化失败!", "", MB_OK);
    Sleep(3000);
    exit(-1);
}

//创建套接字
SOCKET serverSocket;
if((serverSocket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP))==INVALID_SOCKET){
    MessageBoxA(NULL, "创建套接字失败!", "", MB_OK);
    Sleep(3000);
    exit(-1);
}

short port = 9000;
struct sockaddr_in serverAddress;
//初始化指定的内存区域
memset(&serverAddress,0,sizeof(sockaddr_in));
serverAddress.sin_family=AF_INET; // 使用IPv4地址,tcp/ip协议族
serverAddress.sin_addr.S_un.S_addr = htonl(INADDR_ANY); // INADDR_ANY是指任意地址,意指后面监听的是任意地址
serverAddress.sin_port = htons(port);

//绑定
if(bind(serverSocket,(sockaddr*)&serverAddress,sizeof(serverAddress))==SOCKET_ERROR){
    MessageBoxA(NULL, "套接字绑定到端口失败!", "", MB_OK);
    Sleep(3000);
    exit(-1);
}

//进入侦听状态,SOMAXCONN表示最多有5个连接队列
if(listen(serverSocket,SOMAXCONN)==SOCKET_ERROR){
    MessageBoxA(NULL, "侦听失败!", "", MB_OK);
    Sleep(3000);
    exit(-1);
}
SOCKET clientSocket;//用来和客户端通信的套接字
struct sockaddr_in clientAddress;//用来和客户端通信的套接字地址
memset(&clientAddress,0,sizeof(clientAddress));//初始化存放客户端信息的内存
int addrlen =sizeof(clientAddress);

//接受连接
if((clientSocket=accept(serverSocket(sockaddr*)&clientAddress,&addrlen))==INVALID_SOCKET){
    MessageBoxA(NULL, "接受客户端连接失败!", "", MB_OK);
    Sleep(3000);
    exit(-1);
}

3、客户端socket的建立、绑定以及连接

SOCKET m_sock;

bool CreatConnect(const std::string &ServerIP, const std::string &ServerPort)
{
    WSADATA wsadata;

    // 初始化套接字
    if ( WSAStartup(MAKEWORD(2,2), &wsadata) != 0 )
    {
        MessageBox(NULL, "套接字初始化失败!", "", MB_OK);
        return false;
    }

    // 创建套接字

    if ( (m_sock=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP))==INVALID_SOCKET )
    {
        MessageBox( NULL,"创建套接字失败!", "", MB_OK);
        return false;
    }
    bool bConnect = Connect(m_sock, ServerIP, ServerPort);
    g_MarkReceive = 1;

    return bConnect;
}

//获取服务器IP
unsigned long GetServerIP(const std::string &ServerIP)
{
    //把字符串的IP地址转化为u_long
    std::string strIP = ServerIP;
    unsigned long ip;
    if((ip=inet_addr(strIP.c_str()))==INADDR_NONE){
        MessageBox(NULL, "不合法的IP地址", "",MB_OK);
        Sleep(3000);
        return 0;
    }
    return ip;
}

bool Connect(SOCKET &sock, const std::string &ServerIP, const std::string &ServerPort)
{
    unsigned long ip = GetServerIP(ServerIP);
    if ( !ip )
        return false;
    short sPort = (short)std::atoi(ServerPort.c_str());
    struct sockaddr_in serverAddress;
    memset(&serverAddress, 0, sizeof(sockaddr_in));
    serverAddress.sin_family = AF_INET;
    serverAddress.sin_addr.S_un.S_addr = ip;
    serverAddress.sin_port = htons(sPort);

    // 建立和服务器的连接
    if ( connect(sock,(sockaddr*)&serverAddress,sizeof(serverAddress))==SOCKET_ERROR )
    {
        MessageBox(NULL, "建立连接失败!", "", MB_OK);
        return false;
    }
    return true;
}

bool RecvData()
{
    _beginthread(Receive,0,&m_sock);//启动接收数据线程
    return true;
}


// 发送信息
void SendMsg(std::string strSendData, const int &iChangData)
{
    if ( 1 == iChangData )
    {
        if(send(m_sock, strSendData.c_str(), strSendData.length(), 0)==SOCKET_ERROR)
        {
            MessageBox(NULL, "发送数据失败!", "", MB_OK);
            return;
        }
    }
    else
        return;
}

// 接受数据
void Receive(void *param)
{
    while(1)
    {
        char buf[32768];
        SOCKET* sock=(SOCKET*)param;
        int nNetTimeout=5000;   //规定时间5秒
        int ret = setsockopt(*sock, SOL_SOCKET, SO_RCVTIMEO, (char *)&nNetTimeout, sizeof(int));
        int bytes = recv(*sock, buf, sizeof(buf), 0);
        if (bytes == SOCKET_ERROR)
        {
            Sleep(5);
            if(errno == EAGAIN)
                MessageBoxA(NULL, "接受数据失败(接收超时)!", "", MB_OK);//超时这个进不去,需要再研究研究,返回值和判断问题
            else
                MessageBoxA(NULL, "接受数据失败(客户端已断开)!", "", MB_OK);
            return;
        }

        buf[bytes]='\0';
        std::string strTmp = buf;
    }
    return;
}

3、客户端和服务器端的主要不同

1、创建sockaddr_in 时有一点不一样,关于IP那一部分:server端是htonl(INADDR_ANY);意指任意IP地址,也可以指定地址端,但是client端必须指定服务器地址;
2、服务器端在建立后要设置监听,以便与客户端连接;而客户端建立连接就可以
这是个人认为server端和client端不同的地方(在代码方面)

接下来是setsockopt、recv、send的介绍

这个网址中有对[setsockopt]完整的介绍(http://blog.csdn.net/maotianwang/article/details/52101634)
对[recv和send]的完整介绍(http://www.cnblogs.com/jianqiang2010/archive/2010/08/20/1804598.html)

猜你喜欢

转载自blog.csdn.net/bloke_come/article/details/77574102