Winsock编程基础2(Winsock编程流程)

1、套接字的创建和关闭
 
//创建套接字
SOCKET socket(
    int af,        //指定套接字使用的地址格式,Winsock只支持AF_INET
    int type,    //套接字类型
    int protocol//配合type使用,使用的协议
);
//---type
/*
* SOCKET_STREAM 流套接字,TCP
* SOCKET_DGRAM    数据报套接字UDP
* SOCK_RAW        原始套接字
*/
//type使用上面两种时,protocol可直接赋0
//创建失败返回 INVALID_SOCKET(-1),可通过WSAGetLastError获得错误代码
//也可以使用WSASocket创建套接字,现在先不讨论
    
//关闭套接字
int closesocket(SOCKET s);    //s为要关闭套接字句柄
 2、绑定IP和端口号
int bind(
    SOCKE s,    //套接字句柄
    const struct socketaddr* name,    //要关联的本地地址
    int nameLen    //地址长度
);
//bind作用在没有建立连接的套接字上

//绑定示例
//填充sockaddr_in结构
sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(4567);    //为0时主机也会自动配置
addr.sin_addr.S_un.S_addr = INADDR_ANY;    //自动使用当前主机配置
//绑定这个套接字到一个本地地址
if(bind(sListen, (LPSOCKADDR)&addr, sizeof(addr)) == SOCKET_ERROR)//sListen是一个套接字
{
    cout << "Failed bind()" << endl;
    return 0;
}
 3、设置套接字进入监听状态
int listen(
    SOCKET s,    //套接字句柄
    int backlog    //监听队列中允许保持的尚未处理的最大连接数,队满客户端会收到WSAECONNREFUSED
);
 4、接受连接请求
SOCKET accept(        //返回实际连接的套接字,与s有相同属性
    SOCKET s,
    struct sockaddr* addr,    //指向sockassr_in结构指针,用于获得对方信息
    int *addrLen    //指向地址长度指针
);
 5、客户端创建套接字后的请求与服务器连接
int connect(
    SOCKET s,    //客户端套接字
    const struct sockaddr FAR *name,    //包含了要连接的服务器的地址信息
    int nameLen
);
 6、收发数据
int send(
    SOCKET s,    //
    const char FAR *buf,    //要发送的数据缓冲区地址
    int Len,    //缓冲区长度
    int flags    //调用方式,常设0
);
int recv(SOCKET s, char FAR *buf, int len, int flags)
简单实例
//服务器端
#include <iostream>
#include <stdio.h>

#include "InitSock.h"

using namespace std;
int main(void)
{
    CInitSock initSock;
    SOCKET sListen = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (sListen == INVALID_SOCKET)
    {
        cout << "Failed socke()" << endl;
        return 0;
    }
    //填充sockaddr_in结构
    sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(4567);    
    addr.sin_addr.S_un.S_addr = INADDR_ANY;    
    //绑定这个套接字到一个本地地址
    if (bind(sListen, (LPSOCKADDR)&addr, sizeof(addr)) == SOCKET_ERROR)
    {
        cout << "Failed bind()" << endl;
        return 0;
    }

    //进入监听模式
    if (listen(sListen, 2) == SOCKET_ERROR)
    {
        cout << "Failed listen()" << endl;
        return 0;
    }

    //循环接受客户端连接请求
    sockaddr_in remoteAddr;    //远程客户端信息
    int nAddrLen = sizeof(remoteAddr);
    SOCKET sClient;
    char szText[] = "TCP Sever Demo!\r\n";
    while (true)
    {//接受新连接
        sClient = accept(sListen, (SOCKADDR *)&remoteAddr, &nAddrLen);
        if (sClient == INVALID_SOCKET)
        {
            cout << "Failed accept()" << endl;
            continue;
        }

        cout << "接受一个连接: " << inet_ntoa(remoteAddr.sin_addr) <<endl;;    //inet_ntoa()实际已过时,只能处理IPv4
        //向客户端发送数据
        send(sClient, szText, strlen(szText), 0);
        //关闭通客户端的连接
        closesocket(sClient);
    }    
    //关闭监听套接字
    closesocket(sListen);
    return 0;
}
 客户端
#include <iostream>
#include <stdio.h>

#include "InitSock.h"

using namespace std;
int main(void)
{
    CInitSock initSock;
    //创建套接字
    SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (s == INVALID_SOCKET)
    {
        cout << "Failed socke()" << endl;
        return 0;
    }
    //也可以在这里调用binding函数绑定一个本地连接
    //否则系统会自动安装
    //...
    //填写远程地址信息
    sockaddr_in servAddr;
    servAddr.sin_family = AF_INET;
    servAddr.sin_port = htons(4567);
    servAddr.sin_addr.S_un.S_addr = INADDR_ANY;

    //注意这里要填写远程服务器的TCP地址
    //本地回环127.0.0.1
    servAddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
    if (connect(s, (sockaddr*)&servAddr, sizeof(servAddr)) == -1)
    {
        cout << "Failed connect()" << endl;
        return 0;
    }

    //接受数据
    char buff[256];
    int nRecv = recv(s, buff, 256, 0);
    if (nRecv > 0)
    {
        buff[nRecv] = '\0';
        cout << buff << endl;
    }
    //关闭套接字
    closesocket(s);
    getchar();
    return 0;
}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
原文地址:https://www.cnblogs.com/chenxingyang/p/9747827.html