做个笔记,注释以基本在代码里,废话不多说 PS:欢迎批评、指正、交流
#include <iostream>
#include <winsock2.h>
using namespace std;
//因为是用codeblocks编写的,所以要
//右击项目-> "build options..."->"linker setting"->"other linker options" 里面添加 “-lws2_32”
//#pragma comment(lib, "ws2_32.lib") 在VC/VS环境下启用
int main()
{
/**< 1! 加载套接字版本库 2.2 */
WSADATA wsaData;
if(0 != WSAStartup(MAKEWORD(2, 2), &wsaData))
{
cout<<"load socket version error"<<endl;
return 0;
}
/**< 1! */
/**< 2! 创建套接字*/
/*
SOCKET socket(
int af, //指定地址族 如AF_INET决定了要用ipv4地址(32位的)与端口号(16位的)的组合
int type, //指定socket类型 常用SOCK_STREAM(面向连接的流式socket)和 SOCK_DGRAM(面向无连接的数据报式socket)
int protocol //指定协议 当为 0 时,自动选择与第二个参数匹配的协议,在不熟悉的情况下,建议一般设为 0
);
*/
SOCKET sockListen = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(sockListen == INVALID_SOCKET)
{
cout<<"create socket error"<<endl;
return 0;
}
/**< 2! */
/**< 3! 绑定 IP 和 端口 */
sockaddr_in svrAddr;
svrAddr.sin_family = AF_INET;
svrAddr.sin_port = htons(8888);
svrAddr.sin_addr.S_un.S_addr = INADDR_ANY;
/*
int bind(
SOCKET s, //描述一个未绑定的套接字的描述符。即不可重复绑定
const struct sockaddr FAR* name, //从sockaddr结构中分配到套接字的地址
int namelen //name参数中值的长度
);
*/
if(bind(sockListen, (sockaddr*)&svrAddr, sizeof(svrAddr)) == INVALID_SOCKET)
{
cout<<"bind error"<<endl;
return 0;
}
/**< 3! */
/**< 4! 开启监听*/
/*
int listen(
SOCKET s, //描述一个绑定的、没有连接的套接字的描述符。
int backlog //等待连接的队列的最大长度。
);
*/
if(listen(sockListen, 10) == INVALID_SOCKET)
{
cout<<"listen error"<<endl;
return 0;
}
/**< 4! */
/**< 5! 数据接收*/
SOCKET sockMSG; //通讯套接字
sockaddr_in remoteAddr; //远程连接地址
int nLen = sizeof(remoteAddr);
/*
SOCKET accept(
__in SOCKET s, //描述一个套接字在监听函数中被置于监听状态的描述符
__out struct sockaddr* addr, //一个可选的指针,用来接收连接实体的地址
__inout int* addrlen //一个可选的指向一个整数的指针,它包含了addr参数所指向的结构的长度
);
*/
sockMSG = accept(sockListen, (sockaddr*)&remoteAddr, &nLen);
if(sockMSG == INVALID_SOCKET)
{
cout<<"accept error"<<endl;
return 0;
}
// remoteAddr.sin_addr 可以获得连接的客户端的IP地址
/**< 5! */
/**< 6! 数据接收和发送*/
char recvBuf[255];
memset(recvBuf, 1, sizeof(recvBuf)); //初始化 每声明一个数组,都应该立即执行初始化操作
while(true)
{
/*
int recv(
SOCKET s, //连接套接字描述符
char FAR* buf, //用于输入数据的缓冲区。
int len, //buf参数的长度。
int flags //标记指定调用的方式。 一般为 0
); 返回接收到的字节数
*/
recv(sockMSG, recvBuf, sizeof(recvBuf), 0);
cout<<recvBuf<<endl;
/*
int send(
SOCKET s, //连接套接字描述符
const char FAR* buf, //包含要传输的数据的缓冲区
int len, //在buf参数中数据的长度
int flags //指示指定调用的方式 一般为 0
); 如果没有发生错误,函数将返回发送的字节总数
*/
const char *sendBuf = "hello TCP client";
send(sockMSG, sendBuf, strlen(sendBuf), 0);
}
/**< 6! */
/**< 7! 释放资源*/
closesocket(sockMSG);
closesocket(sockListen);
WSACleanup();
/**< 7! */
return 0;
}