about socket practice

From

socket通信的整个过程可以比喻是电话机通信

server:

#include

int main(int argc, char* argv[])
{
    WSADATA wsaData;

    SOCKET hServSock,hClntSock;

    SOCKADDR_IN servAddr,clntAddr;

    int szClntAddr;

    char message[] = "Hello World!";
    if(argc != 2)
    {
        cout<<"Usage:"< \n"<    }
    if(WSAStartup(MAKEWORD(2,2),&wsaData) != 0)      //完成对Winsock服务的初始化
    {
        cout<<"wsaStartup error!"<    }

    hServSock = socket(PF_INET,SOCK_STREAM,0);      // 创建电话机

    /***************************************************************************
    成功返回文件描述符(linux一切皆文件,文件描述符可以看做文件的数字代号)
    失败返回-1(INVALID_SOCKET)
    ****************************************************************************/

    if(hServSock == INVALID_SOCKET)
    {
        cout <<"socket() error!"<    }
    /***************************************************************************
    servAddr 定义了服务端使用Ipv4 32位地址协议(AF_INET)

    使用通信端口号 sin_port

    作为服务器,ip地址不定,指定为INADDR_ANY,系统将绑定默认网卡即自身IP地址

    htonl:将一个无符号短整型的主机数值转换为网络字节顺序,即大尾顺序(big-endian)

    从而可以保证数据在不同主机之间传输时能够被正确解释
    ****************************************************************************/
    memset(&servAddr,0,sizeof(servAddr));

    servAddr.sin_family = AF_INET;

    servAddr.sin_port = htons(atoi(argv[2]));

    servAddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);


    if(bind(hServSock,(SOCKADDR*) & servAddr,sizeof(servAddr)) == SOCKET_ERROR)   //给电话机分配电话号码
    {
        cout <<"bind error"<    }

    if(listen(hServSock,5) == SOCKET_ERROR)   //连接电话线,第二个参数backlog为此队列允许的最大个数
    {
        cout << "listen() error"<    }

    szClntAddr = sizeof(clntAddr);

    hClntSock = accept(hServSock,(SOCKADDR*) &clntAddr,&szClntAddr);  //拿起话筒,生成套接字文件描述符,基于此套接字传递消息,服务端会阻塞于此

    if(hClntSock == INVALID_SOCKET)
    {
        cout << "accept error"<    }

    send(hClntSock,message,sizeof(message),0);    //发送数据

    closesocket(hClntSock);
    closesocket(hServSock);

 WSACleanup();
    return 0;
}

client:

#include
#include
#include

using namespace std;
int main(int argc ,char* argv[])
{
    WSADATA wsaData;
    SOCKET hSocket;
    SOCKADDR_IN servAddr;

    char message[30]= "";
    int strLen;
    if(WSAStartup(MAKEWORD(2,2),&wsaData) !=0)
    {
        cout<<"WSAStartup error"<    }
    hSocket = socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);
    if(hSocket == INVALID_SOCKET)
    {
        cout <<"socket() error"<    }
    memset(&servAddr,0,sizeof(servAddr));
    servAddr.sin_family = AF_INET;
    servAddr.sin_addr.S_un.S_addr = inet_addr(argv[2]);
    servAddr.sin_port = htons(atoi(argv[3]));

    if(connect(hSocket,(SOCKADDR*)&servAddr,sizeof(servAddr)) == SOCKET_ERROR)     //连接指定服务端
    {
        cout<<"connect error"<    }
    strLen = recv(hSocket,message,sizeof(message)-1,0);      //接收数据
    if(strLen == -1)
    {
        cout << "read() error"<    }
    printf("message from server : %s \n",message);
    closesocket(hSocket);
    WSACleanup();
    system("pause");
    return 0;
}

 

与一般的小程序不同,window socket相关的库并没有默认链接,需要手动链接该静态库about socket practice_第1张图片

若没有链接该库,socket相关的函数实现都是无法找到而报错的,链接好之后,#include包含接口头文件直接使用即可。

当然cpp中还要另一种链接该库的方式,#pragma comment(lib,"ws2_32.lib"),通过c语言的预编译指令告诉程序需要链接该库。

 上面用到了main参数,使用时在这设置

about socket practice_第2张图片

这样设置main函数的参数第一个默认为可执行文件的地址,我们使用时从argv[1]开始使用

通过accept之后3次握手建立连接后,数据就可以双向发送接收了。

你可能感兴趣的:(about socket practice)