服务端首先是确定协议版本。首先定义一个结构体
WSADATA wsadata;
这个结构体是啥呢?
是Windows下得到广泛应用的、开放的、支持多种协议的网络编程接口。大家晓得了吧。
让我们看看这个结构体。
typedef struct WSAData {
WORD wVersion; //低位字节指定主版本号。
WORD wHighVersion; //高阶字节指定次要版本号;
char szDescription[WSADESCRIPTION_LEN+1];//
char szSystemStatus[WSASYS_STATUS_LEN+1];//
unsigned short iMaxSockets;//
unsigned short iMaxUdpDg;//
char FAR *lpVendorInfo;//
} WSADATA, *LPWSADATA;
然后调用下面这个函数启动对winsock dll的使用,那么就要判断这个函数是否要成功
if(WSAStartup(MAKEWORD(2,2),&wsadata)!=0)
{
cout <<"启动失败!"<<endl;
return;
}
启动以后就要判断高低字节位有没有问题。
//判断高低版本对不对
if (LOBYTE(wsadata.wVersion) != 2 || HIBYTE(wsadata.wHighVersion) != 2)
{
cout << "版本不对" << endl;
return;
}
//1.确定协议版本
//定义一个结构体
WSADATA wsadata;
//启动winsock dll,返回值不为零即为启动失败
if (WSAStartup(MAKEWORD(2, 2), &wsadata) != 0)
{
cout << "调用winscok.dll 失败" << endl;
return -1;
}
cout << "调用winscok.dll 失败\n" << endl;
//判断高低版本对不对
if (LOBYTE(wsadata.wVersion) != 2 || HIBYTE(wsadata.wHighVersion) != 2)
{
cout << "版本不对,%d" << GetLastError() << endl;
return -1;
}
cout << "版本正确"<< endl;
第二步,创建socket,分配套接字句柄
第一个SOCK_STREAM(缺省函数):
这里采用INET,tcp协议。
//2.创建socket
SOCKET servicesocket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if (servicesocket == SOCKET_ERROR)
{
cout << "创建socket失败!" << endl;
//因为创建失败,使用要清理协议版本信息
WSACleanup();
return -1;
}
cout << "创建socket成功!" << endl;
第三步,确定协议地址簇
typedef struct sockaddr_in {
ADDRESS_FAMILY sin_family;
USHORT sin_port;
IN_ADDR sin_addr;
CHAR sin_zero[8];
} SOCKADDR_IN, *PSOCKADDR_IN;
SOCKADDR_IN结构为AF_INET地址系列指定传输地址和端口。
//3.确定协议地址簇, SOCKADDR_IN结构为AF_INET地址系列指定传输地址和端口
SOCKADDR_IN addr = { 0 };
addr.sin_family = AF_INET; //与socket保持一致
addr.sin_addr.S_un.S_addr = inet_addr("192.168.31.167");//输入服务端的ip地址,要注意转换
addr.sin_port = htonl(11223);//注意大小端,还有尽量不占用其他应用端口号,要吧端口号设置大一点
第四步 绑定
//4.绑定 把socket和协议地址簇绑定
if (-1 == bind(servicesocket, (sockaddr*)&addr, sizeof addr))
{
cout << "绑定失败!" << endl;
//那就要关闭socket,然后清理协议
closesocket(servicesocket);
WSACleanup();
return -1;
}
cout << "绑定成功" << endl;
第五步 监听
//5.监听
//监听的数量
if (listen(servicesocket, 10) == -1)
{
cout << "监听失败!" << endl;
//那就要关闭socket,然后清理协议
closesocket(servicesocket);
WSACleanup();
return -1;
}
cout << "监听成功" << endl;
第六步 连接
调用此成员函数以接受套接字上的连接。
virtual BOOL Accept(
CAsyncSocket& rConnectedSocket,
SOCKADDR* lpSockAddr = NULL,
int* lpSockAddrLen = NULL
);
//6.接受客户端连接
SOCKET clientsocket = accept(servicesocket,(sockaddr*)NULL,(int*)NULL);
if (clientsocket == SOCKET_ERROR)
{
cout << "客户端连接失败!" << endl;
//那就要关闭socket,然后清理协议
closesocket(servicesocket);
WSACleanup();
return -1;
}
cout << "连接成功" << endl;
第七步 通信
recv函数从连接的套接字或绑定的无连接套接字接收数据
int recv(
_In_ SOCKET s,
_Out_ char *buf,
_In_ int len,
_In_ int flags
);
//7.通信
char buffer[256];
while (1)
{
int num = recv(servicesocket,buffer,255,NULL);
buffer[num] = 0;
cout << buffer << endl;
}
第八步 关闭
closesocket(servicesocket);
第九步 清理
WSACleanup();
总的服务端代码:
#include <iostream>
#include <Winsock2.h>
#pragma comment (lib,"ws2_32.lib")
using namespace std;
int main(void)
{
//1.确定协议版本
//定义一个结构体
WSADATA wsadata;
//启动winsock dll,返回值不为零即为启动失败
if (WSAStartup(MAKEWORD(2, 2), &wsadata) != 0)
{
cout << "调用winscok.dll 失败" << endl;
return -1;
}
cout << "调用winscok.dll 成功\n" << endl;
//判断高低版本对不对
if (LOBYTE(wsadata.wVersion) != 2 || HIBYTE(wsadata.wHighVersion) != 2)
{
cout << "版本不对,%d" << GetLastError() << endl;
return -1;
}
cout << "版本正确"<< endl;
//2.创建socket
SOCKET servicesocket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if (servicesocket == SOCKET_ERROR)
{
cout << "创建socket失败!" << endl;
//因为创建失败,使用要清理协议版本信息
WSACleanup();
return -1;
}
cout << "创建socket成功!" << endl;
//3.确定协议地址簇, SOCKADDR_IN结构为AF_INET地址系列指定传输地址和端口
SOCKADDR_IN addr = { 0 };
addr.sin_family = AF_INET; //与socket保持一致
addr.sin_addr.S_un.S_addr = inet_addr("192.168.31.167");//输入服务端的ip地址,要注意转换
addr.sin_port = htons(11223);//注意大小端,还有尽量不占用其他应用端口号,要吧端口号设置大一点
//4.绑定 把socket和协议地址簇绑定
if (-1 == bind(servicesocket, (sockaddr*)&addr, sizeof addr))
{
cout << "绑定失败!" << endl;
//那就要关闭socket,然后清理协议
closesocket(servicesocket);
WSACleanup();
return -1;
}
cout << "绑定成功" << endl;
//5.监听
//监听的数量
if (listen(servicesocket, 10) == -1)
{
cout << "监听失败!" << endl;
//那就要关闭socket,然后清理协议
closesocket(servicesocket);
WSACleanup();
return -1;
}
cout << "监听成功" << endl;
//6.接受客户端连接
SOCKET clientsocket = accept(servicesocket,(sockaddr*)NULL,(int*)NULL);
if (clientsocket == SOCKET_ERROR)
{
cout << "客户端连接失败!" << endl;
//那就要关闭socket,然后清理协议
closesocket(servicesocket);
WSACleanup();
return -1;
}
cout << "连接成功" << endl;
//7.通信
char buffer[256];
while (1)
{
cout << "开始通信" << endl;
int num = recv(servicesocket,buffer,255,NULL);
buffer[num] = 0;
cout << buffer << endl;
}
//8.断开连接
closesocket(servicesocket);
//9.清理版本协议信息
WSACleanup();
return 0;
}
接下来是客户端
客户端同理啦
只要一个连接服务端和通信有点区别
#include <iostream>
//添加头文件
#include <winsock2.h>
#include <windows.h>
#pragma comment (lib,"ws2_32.lib")
using namespace std;
int main(void)
{
//1.确定协议版本
WSADATA cwsadata;
if (WSAStartup(MAKEWORD(2, 2), &cwsadata) != 0)
{
cout << "确定协议版本失败" << endl;
return -1;
}
cout << "确定协议版本成功" << endl;
//判断高低版本
if (LOBYTE(cwsadata.wVersion) != 2 || HIBYTE(cwsadata.wHighVersion) != 2)
{
cout << "版本错误" << endl;
return -1;
}
cout << "版本正确" << endl;
//2.创建socket
SOCKET clientsocket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if (clientsocket == SOCKET_ERROR)
{
cout << "创建socket失败" << endl;
closesocket(clientsocket);
WSACleanup();
return -1;
}
//3获取服务器协议簇
SOCKADDR_IN addr = { 0 };
addr.sin_family = AF_INET;
addr.sin_addr.S_un.S_addr = inet_addr("192.168.31.167");
addr.sin_port = htons(11223);
//4连接服务器
if (connect(clientsocket, (sockaddr*)&addr, sizeof addr) == SOCKET_ERROR)
{
cout << "连接失败" << GetLastError() << endl;
closesocket(clientsocket);
WSACleanup();
return -1;
}
cout << "连接成功" << endl;
//5通信
char buffer[256];
while (1)
{
cout <<"开始通信:";
cin >> buffer;
send(clientsocket, buffer, strlen(buffer), NULL);
}
//6关闭
closesocket(clientsocket);
//7清理
WSACleanup();
return 0;
}