Windows Socket 学习编程
最近需要调试socket程序,记录一下socket的demo。由于socket有多种情况,一下分开讨论。
阻塞式单Client模式
这种是最基本的模式,Server只等待一个Client连接,这种可用于两个进程或者线程之间的通信。
Server Code
void server(void* argc)
{
WSADATA wd;
WSAStartup(MAKEWORD(2, 2), &wd);
/* 创建套接字 */
SOCKET sktServer = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sktServer == INVALID_SOCKET)
{
printf("socket server create fail
");
return;
}
sockaddr_in addrSer = { 0 };
addrSer.sin_family = AF_INET; //服务器的IPV4协议
addrSer.sin_port = htons(8080); //服务器的端口
addrSer.sin_addr.s_addr = inet_addr("127.0.0.1");//服务器的IP
/* 绑定套接字*/
int ret = bind(sktServer, (sockaddr*)&addrSer, sizeof(addrSer));
if (ret == SOCKET_ERROR)
{
printf("socket server bind fail
");
return;
}
/* 开始监听 */
listen(sktServer, 1);
/* 接收到client端连接 */
SOCKET sktClient = accept(sktServer, NULL, NULL);
/* 进入处理线程 */
char buf[1024];
while (true) {
/* 接受客户端发送的数据 */
printf("server recv start...
");
recv(sktClient, buf, sizeof(buf), 0);
printf("recv %s
", buf);
/* 向客户端发送数据 */
send(sktClient, buf, strlen(buf) + 1, 0);
}
WSACleanup();
}
阻塞式Client Code
void client(void* argc)
{
WSADATA wd;
WSAStartup(MAKEWORD(2, 2), &wd);
/* 创建客户端套接字 */
SOCKET sktClinet = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sktClinet == INVALID_SOCKET)
{
printf("socket client create fail
");
return;
}
sockaddr_in addrSer = { 0 };
addrSer.sin_family = AF_INET;//要接的服务器的IPV4协议
addrSer.sin_port = htons(8080);//要连接的服务器的端口
addrSer.sin_addr.s_addr = inet_addr("127.0.0.1");//要连接的服务器的IP
/* 连接本地服务器 */
connect(sktClinet, (sockaddr*)&addrSer, sizeof(addrSer));
const char* str = "hello world";
char buf[1024] = { 0 };
while (true) {
send(sktClinet, str, strlen(str) + 1, 0);//向服务器发送数据
recv(sktClinet, buf, sizeof(buf), 0);//接受服务器发送的数据
printf("client recv %s
", buf);
Sleep(1);
}
WSACleanup();
}
非阻塞式Client模式
Server端
void nonblocking_server(void* argc)
{
WSADATA wd;
WSAStartup(MAKEWORD(2, 2), &wd);
SOCKET sktServer = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sktServer == INVALID_SOCKET)
{
printf("socket server create fail
");
return;
}
sockaddr_in addrSer = { 0 };
addrSer.sin_family = AF_INET; //服务器的IPV4协议
addrSer.sin_port = htons(8080); //服务器的端口
addrSer.sin_addr.s_addr = inet_addr("127.0.0.1");//服务器的IP
/* 绑定套接字*/
int ret = bind(sktServer, (sockaddr*)& addrSer, sizeof(addrSer));
if (ret == SOCKET_ERROR)
{
printf("socket server bind fail
");
return;
}
/* 开始监听 */
listen(sktServer, 1);
SOCKET sktClient = accept(sktServer, NULL, NULL);
char buf[1024];
int count = 0;
while (true) {
count++;
sprintf(buf, "hello world count %d
", count);
send(sktClient, buf, strlen(buf) + 1, 0);//向客户端发送数据
Sleep(1); /* 延迟1s */
}
WSACleanup();
}
非阻塞Client端
void nonblocking_client(void* argc)
{
int count = *(int*)argc;
WSADATA wd;
WSAStartup(MAKEWORD(2, 2), &wd);
//创建客户端套接字
SOCKET sktCli = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
unsigned long ul = 1;
/* 非阻塞模式 */
ioctlsocket(sktCli, FIONBIO, (unsigned long*)&ul);
/* 阻塞超时模式 */
int nNetTimeout = 500;//500ms,
/* 设置发送超时 */
//setsockopt(sktCli, SOL_SOCKET, SO_SNDTIMEO, (char*)&nNetTimeout, sizeof(int));
/* 设置接收超时 */
//setsockopt(sktCli, SOL_SOCKET, SO_RCVTIMEO, (char*)&nNetTimeout, sizeof(int));
sockaddr_in addrSer = { 0 };
addrSer.sin_family = AF_INET;//要接的服务器的IPV4协议
addrSer.sin_port = htons(8080);//要连接的服务器的端口
addrSer.sin_addr.s_addr = inet_addr("127.0.0.1");//要连接的服务器的IP
//连接服务器
connect(sktCli, (sockaddr*)& addrSer, sizeof(addrSer));
char buf[1024];
while (1)
{
recv(sktCli, buf, sizeof(buf), 0);//接受服务器发送的数据
printf("[server] %s
", buf);
}
WSACleanup();
}
多Client模式
服务器处理接收多个Client的模式
void mulitClient_server(void* argc)
{
WSADATA wd;
WSAStartup(MAKEWORD(2, 2), &wd);
SOCKET skt = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
sockaddr_in addrSer = { 0 };
addrSer.sin_family = AF_INET; //服务器的IPV4协议
addrSer.sin_port = htons(8080); //服务器的端口
addrSer.sin_addr.s_addr = inet_addr("127.0.0.1");//服务器的IP
bind(skt, (sockaddr*)& addrSer, sizeof(addrSer));
listen(skt, 5);
char buf[1024];
sockaddr_in addr = { 0 };
int addrLen = sizeof(addr);
while (true) {
SOCKET sktCli = accept(skt, (sockaddr*)&addr, &addrLen);
if (sktCli == INVALID_SOCKET) {
printf("[client] accpet error ...
");
return;
}
printf("[client] socket:%d ip:%s port:%d accept ...
", sktCli, inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
/* 单独创建处理线程 */
}
WSACleanup();
}