C语言Socket基本用法

要是用Socket实现基本的通信,主要分以下几个步骤。

1.初始化

函数原型:int WSAStartup( WORD wVersionRequired, LPWSADATA lpWSAData );

参数1:版本选择

参数2:设置一个指向WSADATA数据类型的指针

返回值为0时,表示该函数执行成功。

Startup = WSAStartup(MAKEWORD(2, 2), &wsadata);
if (Startup != 0)
{
    printf("Failed to WSAStartup !\n");
    break;
}

2.申请Socket

函数原型:int socket( int af, int type, int protocol);

参数1:选择地址族(如:AF_INET为ipv4,AF_INET6为ipv6)

参数2:选择套接字类型

参数3:选择协议

返回值:返回套接字描述符

SrvSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (INVALID_SOCKET == SrvSocket)
{
    printf("Socket invoke failed !\n");
    break;
}

3.设置Socket地址及端口

需声明一个SOCKADDR_IN类型的结构体,具体示例如下

SOCKADDR_IN			LocalAddr;

LocalAddr.sin_family = AF_INET;		//地址族,如AF_INET,带标TCP/IP地址族
LocalAddr.sin_addr.S_un.S_addr = 0;	//存储IP地址
LocalAddr.sin_port = htons(26822);	//存储端口号(htons将整型变量从主机字节顺序转变成网络字节顺序)

memset(LocalAddr.sin_zero, 0x0, sizeof(LocalAddr.sin_zero));
//sin_zero是为了让sockaddr与sockaddr_in两个数据结构保持大小相同而保留的空字节
//用来将sockaddr_in结构填充到与struct sockaddr同样的长度,可以用memset()函数将其置为零。

4.绑定IP地址

函数原型:int bind( SOCKET s, const sockaddr *addr, int namelen );

参数1:套接字描述符

参数2:指向要分配给绑定套接字的本地地址的sockaddr结构的指针

参数3:名称参数所指向的值的长度(以字节为单位)

SrvBind = bind(SrvSocket, (SOCKADDR*)&LocalAddr, sizeof(SOCKADDR_IN));
if (0 != SrvBind)
{
    printf("Failed to bind !\n");
    printf("Bind Error Code:%u", WSAGetLastError());
    break;
}

5.监听Socket

函数原型:int listen( SOCKET s, int backlog );

参数1:套接字描述符

参数2:挂起连接队列的最大长度。如果将backlog设置为SOMAXCONN,则负责套接字s的基础服务提供商会将backlog设置为最大合理值。没有标准条款来获取实际积压值。

SrvListen = listen(SrvSocket, 5);

if (0 != SrvListen)
{
    printf("Failed to listen !\n");
    break;
}

6.接受链接

函数原型:SOCKET WSAAPI accept( SOCKET s, sockaddr *addr, int *addrlen );

参数1:标示一个已处于监听状态下的套接字

参数2:通信层已知的指向接收连接实体地址的缓冲区的可选指针。addr参数的确切格式由创建sockaddr结构的套接字时建立的地址族确定 。

参数3:指向整数的可选指针,该整数包含addr参数指向的结构的长度。

AddrLen = sizeof(Clientaddr);
AcceptSocket = accept(SrvSocket, (SOCKADDR*)&Clientaddr, &AddrLen);
if (INVALID_SOCKET == AcceptSocket)
{
    printf("Accept error !\n");
    break;
}