winsock就是在Windows下的网络套接字编程,现在使用的是Windows Socket 2,是专门为C/C++编程而设计的。
Microsoft给出了使用winsock的教程Microsoft winsock
以TCP为例,客户端需要做的事情有
(1)WSAStartup初始化Winsock API
(2)getaddrinfo
(3)Create Socket
(4)Connect
到这里就完成连接,然后就能用send函数和recv函数来进行发送和接受
(5)shutdown关闭连接
服务器端要做的事情如下
(1)WSAStartup初始化Winsock API
(2)getaddrinfo
(3)Create Socket
(4)Bind
把套接字和网络端口号绑定
(5)Listen
监听端口号
(6)Accept
当有客户端发送Connect请求之后,服务器端才会Accept,Accept之后就能与客户端之间通过send和recv函数进行发送和接受
(7)shutdown关闭连接
我把客户端和服务器端的Socket写到一个类里面,要实现什么样的功能只需要在外部调用即可。
头文件
#include
#include
#include
#pragma comment(lib, "Ws2_32.lib")
#define LEN 512
using namespace std;
class Socket
{
public:
//func
Socket();
void TCPSocketS(char* port);
void TCPSocketC(char* addr, char* port);
//common
void myInit();
void myGetaddrinfo(char* socktype, char* protocol, char* addr, char* port);
//difference
void myRecvC();
void mySendC();
void mySocketC();
void shutdownC();
void myRecvS();
void mySendS();
void mySocketS();
void shutdownS();
//server
void myBind();
void myListen();
void myAccept();
//client
void myConnect();
private:
WSADATA wsaData;
struct addrinfo *result, hints;
SOCKET ClientSocket, ListenSocket, ConnectSocket;
char recvbuf[LEN];
char sendbuf[LEN];
};
cpp文件
#include "Socket.h"
#include
#include
using namespace std;
Socket::Socket()
{
//initial
result = NULL;
}
void Socket::myInit()
{
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
{
printf("WSAStartup failed\n");
}
else
{
printf("WSAStartup success\n");
}
}
void Socket::myGetaddrinfo(char* role, char* protocol,
char* addr, char* port)
{
//
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_INET;
if (protocol == "TCP")
//if (strcmp(protocol, "TCP") == 0)
{
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
}
else if (strcmp(protocol, "UDP") == 0)
{
hints.ai_socktype = SOCK_DGRAM;
hints.ai_protocol = IPPROTO_UDP;
}
else
{
printf("getaddrinfo protocol fail\n");
}
if (strcmp(role, "Server") == 0)
{
hints.ai_flags = AI_PASSIVE;
}
//getaddrinfo
if (getaddrinfo(addr, port, &hints, &result) != 0)
{
printf("getaddrinfo failed\n");
}
else
{
printf("getaddrinfo success\n");
}
}
void Socket::myRecvS()
{
int iResult;
iResult = recv(ClientSocket, recvbuf, LEN, 0);
if (iResult > 0)
{
printf("Bytes received: %d\n", iResult);
recvbuf[iResult] = '\0';
printf("string is %s\n", recvbuf);
}
else if (iResult == 0)
printf("Connection closed\n");
else
{
printf("recv failed: %d\n", WSAGetLastError());
}
}
void Socket::myRecvC()
{
int iResult;
iResult = recv(ConnectSocket, recvbuf, LEN, 0);
if (iResult > 0)
{
printf("Bytes received: %d\n", iResult);
recvbuf[iResult] = '\0';
printf("string is %s\n", recvbuf);
}
else if (iResult == 0)
printf("Connection closed\n");
else
{
printf("recv failed: %d\n", WSAGetLastError());
}
}
void Socket::mySendC()
{
printf("Input: ");
scanf("%s", sendbuf);
int iResult;
iResult = send(ConnectSocket, sendbuf, (int)strlen(sendbuf), 0);
if (iResult == SOCKET_ERROR)
{
printf("send failed\n");
closesocket(ConnectSocket);
WSACleanup();
}
}
void Socket::mySendS()
{
printf("Input: ");
scanf("%s", sendbuf);
int iResult;
iResult = send(ClientSocket, sendbuf, (int)strlen(sendbuf), 0);
if (iResult == SOCKET_ERROR)
{
printf("send failed\n");
closesocket(ClientSocket);
WSACleanup();
}
}
void Socket::mySocketC()
{
ConnectSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
}
void Socket::mySocketS()
{
ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
}
void Socket::shutdownC()
{
if (shutdown(ConnectSocket, SD_SEND) == SOCKET_ERROR)
{
printf("shutdown failed: %d\n", WSAGetLastError());
}
closesocket(ConnectSocket);
WSACleanup();
}
void Socket::shutdownS()
{
if (shutdown(ClientSocket, SD_SEND) == SOCKET_ERROR)
{
printf("shuwdown failed: %d\n", WSAGetLastError());
}
closesocket(ClientSocket);
WSACleanup();
}
//Server func
void Socket::myBind()
{
if (bind(ListenSocket, result->ai_addr, (int)result->ai_addrlen) == SOCKET_ERROR)
{
printf("bind failed\n");
closesocket(ListenSocket);
WSACleanup();
}
else
{
printf("bind success\n");
}
freeaddrinfo(result);
}
void Socket::myListen()
{
if (listen(ListenSocket, SOMAXCONN) == SOCKET_ERROR)
{
printf("listen fail\n");
closesocket(ListenSocket);
WSACleanup();
}
else
{
printf("listen success\n");
}
}
void Socket::myAccept()
{
ClientSocket = accept(ListenSocket, NULL, NULL);
if (ClientSocket == INVALID_SOCKET)
{
printf("accept fail\n");
closesocket(ListenSocket);
WSACleanup();
}
else
{
printf("accept success\n");
}
}
//Client func
void Socket::myConnect()
{
if (connect(ConnectSocket, result->ai_addr, (int)result->ai_addrlen) == SOCKET_ERROR)
{
printf("connect error\n");
closesocket(ConnectSocket);
ConnectSocket = INVALID_SOCKET;
}
freeaddrinfo(result);
if (ConnectSocket == INVALID_SOCKET)
{
printf("Unable to connect to server\n");
WSACleanup();
}
}
//packet func
void Socket::TCPSocketS(char* port)
{
myInit();
myGetaddrinfo("Server", "TCP", NULL, port);
mySocketS();
myBind();
myListen();
while (true)
{
myAccept();
myRecvS();
}
}
void Socket::TCPSocketC(char* addr, char* port)
{
myInit();
myGetaddrinfo("Client", "TCP", addr, port);
mySocketC();
myConnect();
mySendC();
shutdownC();
}
主函数调用只需要几行技能完成客户端和服务器端的配置和使用
客户端
#include "Socket.h"
#define port "8889"
#define addr "127.0.0.1"
#define addr2 NULL
int main()
{
Socket a;
while (true)
{
a.TCPSocketC(addr, port);
}
return 1;
}
服务器端
#include "Socket.h"
#define port "8889"
#define addr "127.0.0.1"
#define addr2 NULL
int main()
{
Socket a;
a.TCPSocketS(port);
return 1;
}
比较基础的winsock编程,自己写的代码,可能有些小bug没发现~