Windows下C语言单线程socket通信

编程环境:CodeBlocks + MinGW

1、服务器端

#include <stdio.h>
#include <string.h>
#include <winsock32.h> // 函数定义头文件,调用API

#pragma comment(lib,"wsk2_32.lib") // Windows socket API

int main()
{
    // 初始化WSA
    WSADATA wsaData;
    WORD sockVersion = MAKEWORD(2,2);
    if(WSAStartup(sockVersion,&wsaData) != 0)
    {
        //不为0说明初始失败
        return 0;
    }

    // 创建socket
    SOCKET sock = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
    // AF_INET 地址描述
    // SOCK_STREAM socket类型
    // IPPROTO_TCP 协议类型
    if(sock == INVALID_SOCKET)
    {
        // socket创建失败
        return 0;
    }

    // 服务器需要绑定端口和IP
    SOCKADDR_IN sin;
    sin.sin_family = AF_INET;
    sin.sin_port = htons(8888);
    sin.sin_addr.S_un.S_addr = INADDR_ANY;
    // INADDR_ANY等价于inet_addr("0.0.0.0");
    // 表示绑定服务器端所有可用IP
    if(bind(sock,(SOCKADDR *)&sin,sizeof(sin)) == SOCKET_ERROR)
    {
        return 0; // 绑定失败
    }

    // 开启监听
    if(listen(sock,5) == SOCKET_ERROR)
    {
        // 等待连接队列为5
        return 0;
    }

    // 接受连接
    SOCKET sClient;
    SOCKADDR_IN rAddr;
    int len = sizeof(rAddr);
    while(1)
    {
        sClient = accept(sock,(SOCKADDR *)&rAddr,&len);
        // 注意&len不可以省略&符号,与bind和connect不同
        if(sClient == INVALID_SOCKET)
        {
            continue; // 连接无效,进行下次等待
        }
        // 打印客户端IP信息
        printf("Connection from : %s\n",inet_ntoa(rAddr));

        // 接收数据
        char revData[255];
        int ret = recv(sClient,revData,255,0);
        // sClient不是sock 0为默认 255为接收长度
        if(recv > 0)
        {
            revData[ret] = '\0'; // 结束字符
            printf(revData);
        }

        // 发送数据
        char *d = "Hello client,i am server!";
        send(sClient,d,strlen(d),0);

        // 关闭连接
        closesocket(sClient);
    }

    // 善后收尾
    closesocket(sock);
    WSACleanup();

    return 0;
}

2、客户端

#incldue <stdio.h>
#include <string.h>

// 不可缺少
#include <winsock32.h>
#pragma comment(lib,"wsk2_32.lib")

int main()
{
    // 初始WSA
    WSADATA wsaData;
    WORD sockVersion = MAKEWORD(2,2);
    if(WSAStartup(sockVersion,&wsaData) != 0)
    {
        return 0;
    }

    // 创建socket
    SOCKET sock = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP));
    if(sock == INVALID_SOCKET)
    {
        return 0;
    }

    // 设置服务器端口和IP,注意和服务器端区分
    SOCKADDR_IN sin;
    sin.sin_family = AF_INET;
    sin.sin_port = htons(8888); // 与服务器一致
    sin.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
    // "127.0.0.1"与服务器绑定地址一致

    if(connect(sock,(SOCKADDR *)&sin,sizeof(sin)) == SOCKET_ERROR)
    {
        return 0; // 连接失败
    }

    // 发送数据,服务器先接收所以客户端先发送
    char *d = "Hello server,i am client!";
    send(sock,d,strlen(d),0);

    // 接收
    char revData[255];
    int ret = recv(sock,revData,255,0);
    if(ret > 0)
    {
        revData[ret] = '\n';
        printf(revData);
    }

    // 善后收尾
    closesocket(sock);
    WSACleanup();
    return 0;
}

3、UDP通信协议
服务器端不再需要接受连接,直接接收发送数据。客户端类似。它们都需要将IPPROTO_TCP改成IPPROTO_UDP。将SOCK_STREAM改成SOCK_DGRAM。

SOCKADDR_IN sin;
int len = sizeof(sin);
while(1)
{
    char revData[255];
    int ret = recvfrom(sock,revData,255,0,(SOCKADDR *)&sin,&len);    // 接收时&len与发送时不同
    if(ret > 0)
    {
        revData[ret] = '\0';
        printf("接受到一个连接:%s\n", inet_ntoa(remoteAddr.sin_addr));
        printf(revData);
    }

    char *d = "hello client!";
    sendto(sock,revData,strlen(d),0,(SOCKADDR *)&sin,sizeof(sin));
}

报类似 undefined reference to `inet_addr@4’错误参考:
http://www.android100.org/html/201501/28/105793.html

最后吐槽一下:C语言的函数好难记( ̄へ ̄)

你可能感兴趣的:(windows,socket,tcp)