Windos Socket的实现

本文介绍Windows Socket编程的基础知识,包括套接字类型如流式套接字和数据报式套接字的区别,以及通过示例代码展示如何创建TCP和UDP的服务端与客户端。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Windos Socket的实现

Windows socket 是microsoft windows的网络程序设计接口,它是从berkeley socket扩展而来,以动态链接库的形式提供给我们使用。windows socket在继承了berkeley socket主要特征的基础上,又对它进行了重要扩充。这些扩充主要是提供了一些异步函数,并增加了符合windows消息驱动特性的网络事件异步选择机制。

套接字类型

流式套接字(SOCK_STREAM)
提供面向连接、可靠地数据传输服务,数据无差错,无重复的发送,并且按照发送顺序接收。流式套接字实际上是基于TCP协议实现的
数据报式套接字(SOCK_DGRAM)
提供无连接服务。数据包以独立包形式发送,不提供无错保证,数据可能丢失或者重复,并且接收顺序混乱。数据包式套接字实际上是基于UDP协议实现的

代码例子

服务端
// WinSocketSrv.cpp : 定义控制台应用程序的入口点。
//


#include "stdafx.h"
#include <winsock2.h>
#include <cstdio>
#include <process.h>
#pragma comment (lib,"ws2_32.lib")


unsigned int _stdcall RecvProc(void*lpParameter)
{
SOCKET*psock=(SOCKET*)lpParameter;
char buf[1024]={0};
if(recv(*psock,buf,1024,0)==SOCKET_ERROR)
{
printf("recv() failed,error code:%d\n",WSAGetLastError());
closesocket(*psock);
_endthreadex(0);
return 0;
}
printf("收到:%s\n",buf);
closesocket(*psock);
_endthreadex(0);
return 1;
}


bool InitSocket()
{
WSADATA wsaData;
WORD wVersion;
ZeroMemory(&wsaData,sizeof(WSADATA));


wVersion=MAKEWORD(2,2);
if(WSAStartup(wVersion,&wsaData)!=0)
{
printf("WSAStartup() failed,error code:%d\n",WSAGetLastError());
return false;
}
if(LOBYTE(wsaData.wVersion)!=2||HIBYTE(wsaData.wVersion)!=2)
{
printf("LOBYTE()、HIBYTE() failed!\n");
WSACleanup();
return false;
}
return true;
}

bool StartSrv(char*szIP,unsigned short usPort,bool bStyle)
{
//bStyle--true TCP;false UDP;
SOCKET sock;
if(bStyle)
{
sock =socket(AF_INET,SOCK_STREAM,0);
if(sock==INVALID_SOCKET)
{
printf("socket() failed,error code:%d\n",WSAGetLastError());
WSACleanup();
return false;
}
SOCKADDR_IN addrSrv;
ZeroMemory(&addrSrv,sizeof(SOCKADDR_IN));
addrSrv.sin_family =AF_INET;
addrSrv.sin_addr.S_un.S_addr=inet_addr(szIP);
addrSrv.sin_port =htons(usPort);
int flag=1;
int len =sizeof(int);
if(setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,(const char*)&flag,len)==SOCKET_ERROR)
{
printf("setsockopt() failed,error code:%d\n",WSAGetLastError());
closesocket(sock);
WSACleanup();
return false;
}
if(bind(sock,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR_IN))==SOCKET_ERROR)
{
printf("bind() failed,error code:%d\n",WSAGetLastError());
closesocket(sock);
WSACleanup();
return false;
}
if(listen(sock,100)==SOCKET_ERROR)
{
printf("listen() failed,error code:%d\n",WSAGetLastError());
closesocket(sock);
WSACleanup();
return false;
}
while(1)
{
SOCKET rs;
SOCKADDR_IN client;
int len =sizeof(SOCKADDR_IN);
ZeroMemory(&client,sizeof(SOCKADDR_IN));
rs=accept(sock,(SOCKADDR*)&client,&len);
if(rs==INVALID_SOCKET)
{
printf("accept() failed,error code:%d\n",WSAGetLastError());
closesocket(sock);
WSACleanup();
return false;
}
HANDLE hTcp =(HANDLE)_beginthreadex(NULL,0,RecvProc,(void*)&rs,0,NULL);
WaitForSingleObject(hTcp,INFINITE);
CloseHandle(hTcp);
}
}
else
{
sock =socket(AF_INET,SOCK_DGRAM,0);
if(sock==INVALID_SOCKET)
{
printf("socket() failed,error code:%d\n",WSAGetLastError());
WSACleanup();
return false;
}
SOCKADDR_IN addrSrv;
ZeroMemory(&addrSrv,sizeof(SOCKADDR_IN));
addrSrv.sin_family=AF_INET;
addrSrv.sin_addr.S_un.S_addr=inet_addr(szIP);
addrSrv.sin_port=htons(usPort);
int flag=1;
int len =sizeof(int);
if(setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,(const char*)&flag,len)==SOCKET_ERROR)
{
printf("setsockopt() failed,error code:%d\n",WSAGetLastError());
closesocket(sock);
WSACleanup();
return false;
}
if(bind(sock,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR_IN))==SOCKET_ERROR)
{
printf("bind() failed,error code:%d\n",WSAGetLastError());
closesocket(sock);
WSACleanup();
return false;
}
while(1)
{
char buf[1024]={0};
SOCKADDR_IN client;
int len =sizeof(SOCKADDR_IN);
ZeroMemory(&client,sizeof(SOCKADDR_IN));


if(recvfrom(sock,buf,1024,0,(SOCKADDR*)&client,&len)==SOCKET_ERROR)
{
printf("recvfrom() failed,error code:%d\n",WSAGetLastError());
closesocket(sock);
WSACleanup();
return false;
}
printf("收到:%s\n",buf);
}
}
return true;
}


int _tmain(int argc, _TCHAR* argv[])
{
if(InitSocket())
{
StartSrv("127.0.0.1",8080,false);
}
printf("exit!\n");
return 0;
}

客户端
// WinSocketClt.cpp : 定义控制台应用程序的入口点。
//


#include "stdafx.h"
#include <winsock2.h>
#include <cstdio>
#pragma comment (lib,"ws2_32.lib")


bool InitSocket()
{
WSADATA wsaData;
WORD wVersion;
ZeroMemory(&wsaData,sizeof(WSADATA));


wVersion=MAKEWORD(2,2);
if(WSAStartup(wVersion,&wsaData)!=0)
{
printf("WSAStartup() failed,error code:%d\n",WSAGetLastError());
return false;
}
if(LOBYTE(wsaData.wVersion)!=2||HIBYTE(wsaData.wVersion)!=2)
{
printf("LOBYTE()、HIBYTE() failed!\n");
WSACleanup();
return false;
}
return true;
}


bool StartSrv(char*szIP,unsigned short usPort,bool bStyle,char*szBuf,int iLen)
{
//bStyle--true TCP;false UDP;
SOCKET sock;
if(bStyle)
{
sock =socket(AF_INET,SOCK_STREAM,0);
if(sock==INVALID_SOCKET)
{
printf("socket() failed,error code:%d\n",WSAGetLastError());
WSACleanup();
return false;
}
SOCKADDR_IN addrSrv;
ZeroMemory(&addrSrv,sizeof(SOCKADDR_IN));
addrSrv.sin_family =AF_INET;
addrSrv.sin_addr.S_un.S_addr=inet_addr(szIP);
addrSrv.sin_port =htons(usPort);
if(connect(sock,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR))==SOCKET_ERROR)
{
printf("connect() failed,error code:%d\n",WSAGetLastError());
closesocket(sock);
WSACleanup();
return false;
}
if(send(sock,szBuf,iLen,0)==SOCKET_ERROR)
{
printf("send() failed,error code:%d\n",WSAGetLastError());
closesocket(sock);
WSACleanup();
return false;
}
}
else
{
sock =socket(AF_INET,SOCK_DGRAM,0);
if(sock==INVALID_SOCKET)
{
printf("socket() failed,error code:%d\n",WSAGetLastError());
WSACleanup();
return false;
}
SOCKADDR_IN addrSrv;
ZeroMemory(&addrSrv,sizeof(SOCKADDR_IN));
addrSrv.sin_family=AF_INET;
addrSrv.sin_addr.S_un.S_addr=inet_addr(szIP);
addrSrv.sin_port=htons(usPort);
if(sendto(sock,szBuf,iLen,0,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR))==SOCKET_ERROR)
{
printf("sendto() failed,error code:%d\n",WSAGetLastError());
closesocket(sock);
WSACleanup();
return false;
}
}
return true;
}


int _tmain(int argc, _TCHAR* argv[])
{
if(InitSocket())
{
while(1)
{
char buf[]="www.baidu.com";
StartSrv("127.0.0.1",8080,false,buf,strlen(buf)+1);
}
}
printf("exit!\n");
return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值