原文地址:点击打开链接
代码如下:
// Server.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include
#pragma comment(lib,"Ws2_32.lib")
int _tmain(int argc, _TCHAR* argv[])
{
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2,2),&wsaData) != 0)
{
printf("load socket version error!\n");
return 0;
}
SOCKET sockListen = socket(AF_INET,SOCK_STREAM,0);
if (sockListen == INVALID_SOCKET)
{
printf("create socket error!\n");
return 0;
}
sockaddr_in srvAddr;
srvAddr.sin_family = AF_INET;
srvAddr.sin_port = htons(80);
srvAddr.sin_addr.S_un.S_addr = INADDR_ANY;
if (bind(sockListen,(sockaddr*)&srvAddr,sizeof(srvAddr)) == INVALID_SOCKET)
{
printf("bind error\n");
return 0;
}
if(listen(sockListen,10) == INVALID_SOCKET)
{
printf("listen error!\n");
return 0;
}
SOCKET sockMsg;
sockaddr_in remoteAddr;
int nLen = sizeof(remoteAddr);
sockMsg = accept(sockListen,(sockaddr *)&remoteAddr,&nLen);
if (sockMsg == INVALID_SOCKET)
{
printf("accept error!\n");
return 0;
}
char recvBuf[255];
memset(recvBuf,1,sizeof(recvBuf));
while (true)
{
recv(sockMsg,recvBuf,sizeof(recvBuf),0);
printf("%s\n",recvBuf);
const char* sendBuf = "hello Client!";
send(sockMsg,sendBuf,strlen(sendBuf),0);
}
closesocket(sockMsg);
closesocket(sockListen);
WSACleanup();
return 0;
}
拆分解释:
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2,2),&wsaData) != 0)
{
printf("load socket version error!\n");
return 0;
}
加载套接字版本库。
WSADATA:用来存储 WSAStartup 函数调用后返回的 Windows Sockets 数据;
WSAStartup 函数:WSA的启用命令;
WSA:Windows Socket Asynchronous Windows异步套接字
SOCKET sockListen = socket(AF_INET,SOCK_STREAM,0);
if (sockListen == INVALID_SOCKET)
{
printf("create socket error!\n");
return 0;
}
创建套接字。
SOCKET socket(int af, int type, int protocol);
int af: 指定地址族;
int type: 指定socket类型,常用SOCKET_STREAM,SOCK_DGRAM;
int protocol: 指定协议,为 0 时,自动选择与第二个参数匹配的协议,一般默认为 0;
sockaddr_in srvAddr;
srvAddr.sin_family = AF_INET;
srvAddr.sin_port = htons(80);
srvAddr.sin_addr.S_un.S_addr = INADDR_ANY;
if (bind(sockListen,(sockaddr*)&srvAddr,sizeof(srvAddr)) == INVALID_SOCKET)
{
printf("bind error\n");
return 0;
}
绑定 IP 和 端口。
int bind(SOCKET s, const struct sockaddr FAR* name, int namelen);
SOCKET s: 描述一个未绑定的套接字的描述符,即不可以重复绑定;
const struct sockaddr FAR* name: 从 sockaddr 结构中分配得到套接字的地址;
int namelen: name 参数中值的长度;
srvAddr.sin_family = AF_INET: 创建套接字时,用该字段指定地址家族,对于 TCP/IP 协议,必须设置为 AF_INET ;
srvAddr.sin_port = htons(80): sin_port设置端口号;
srvAddr.sin_addr.S_un.S_addr = INADDR_ANY: 设置IP
if(listen(sockListen,10) == INVALID_SOCKET)
{
printf("listen error!\n");
return 0;
}
开启监听。
int listen(SOCKET s, int blacklog);
SOCKET s: 描述一个绑定的、没有连接的套接字的描述符;
int blacklog: 等待连接的队列的最大长度;
SOCKET sockMsg;
sockaddr_in remoteAddr;
int nLen = sizeof(remoteAddr);
sockMsg = accept(sockListen,(sockaddr *)&remoteAddr,&nLen);
if (sockMsg == INVALID_SOCKET)
{
printf("accept error!\n");
return 0;
}
数据接收。
SOCKET sockMsg: 通讯套接字;
sockaddr_in remoteAddr: 远程连接地址;
SOCKET accept(_in SOCKET s, _out struct sockaddr* addr, _inout int *addrlen);
in SOCKET s: 描述一个套接字在监听函数中被置于监听状态的描述符;
_out struct sockaddr* addr: 一个可选的指针,用来接收连接实体的地址;
_inout int *addrlen: 一个可选的指向一个整数的指针,它包含了 addr 参数所指向的结构的长度;
char recvBuf[255];
memset(recvBuf,1,sizeof(recvBuf));
while (true)
{
recv(sockMsg,recvBuf,sizeof(recvBuf),0);
printf("%s\n",recvBuf);
const char* sendBuf = "hello Client!";
send(sockMsg,sendBuf,strlen(sendBuf),0);
}
数据接收和发送。
memset(): 此函数为新申请的内存做初始化工作;
int recv(SOCKET s, char FAR *buf, int len, int flags); 返回接收到的字节数
SOCKET s: 连接套接字描述符;
char FAR *buf: 用于输入数据的缓冲区;
int len: buf参数的长度;
int flags: 标记指定调用的方式,一般为 0;
int send(SOCKET s, char FAR *buf, int len, int flags);如果没有发生错误,函数将返回发送的字节数
SOCKET s: 连接套接字描述符;
char FAR *buf: 包含要传输的数据的缓冲区;
int len: buf参数的长度;
int flags: 标记指定调用的方式,一般为 0;
closesocket(sockMsg);
closesocket(sockListen);
WSACleanup();
释放资源。