通过winsock的学习,如下实现简单的服务器和客户端的程序,
服务器程序
程序实现的流程大致如下:
- 加载winsock动态库
- 初始化winsock
- 创建socket变量,并设置协议,IP和端口
- 绑定端口
- 监听端口
- 等待客户端连接
- 接收和发送数据
- 关闭Socket
#include
#include
#include
#pragma comment(lib, "ws2_32.lib") //引入动态链接库
using namespace std;
int main(int argc, char* argv[]) {
WSADATA wsaData;
SOCKET servSock;
SOCKET clientSock;
const int BUF_SIZE = 30;
char msg[BUF_SIZE];
SOCKADDR_IN servAddr, clientAddr;
int bind_status;
int recv_status;
int clientAddrLen = sizeof(SOCKADDR);
int accept_cnt = 0;
WORD ws_version = MAKEWORD(2, 2);
// 参数个数检查
/*
if (argc != 2)
{
cout << "Usage:" << argv[0] << "" << endl;
return -1;
}
*/
// 初始化winsock
if (WSAStartup(ws_version, &wsaData) != 0)
{
cout << "WSAStartup() error" << endl;
return -1;
}
// 创建socket接口
servSock = socket(PF_INET, SOCK_STREAM, 0);
if (servSock == INVALID_SOCKET)
{
cout << "UDP socket creation error" << endl;
return -1;
}
memset(&servAddr, 0, sizeof(servAddr));
servAddr.sin_family = AF_INET; // 协议
servAddr.sin_addr.s_addr = htonl(INADDR_ANY); // IP:任意IP
//servAddr.sin_port = htons(atoi(argv[1])); // 端口
servAddr.sin_port = htons(5050); // 端口
// 绑定端口
bind_status = bind(servSock, (SOCKADDR*)&servAddr, sizeof(SOCKADDR));
if (bind_status == SOCKET_ERROR)
{
cout << "bind error: Fail to bind" << endl;
}
else
{
cout << "bind successfully" << endl;
}
// 监听端口
listen(servSock, 5); // max = 5
cout << "server start, begin to listening..." << endl;
while (true)
{
cout << "等待连接..." << endl;
// 接受连接
clientSock = accept(servSock, (SOCKADDR*)&clientAddr, &clientAddrLen);
if (clientSock == INVALID_SOCKET)
{
cout << "Accept Error: Fail to accept client" << endl;
}
else
{
accept_cnt++;
cout << "Accept success" << endl;
cout << "编号: " << accept_cnt << endl;
cout << "Port: " << ntohs(clientAddr.sin_port) << endl;
char outputStr[INET_ADDRSTRLEN];
PCSTR ptr = inet_ntop(AF_INET, &clientAddr.sin_addr, outputStr, sizeof(outputStr));
cout << "IP: " << outputStr << endl;
//cout << "IP: " << inet_ntoa(clientAddr.sin_addr) << endl;
recv_status = recv(clientSock, msg, 30, 0);
if (recv_status > 0)
{
cout << "收到: ";
msg[recv_status] = 0x00;
cout << msg << endl;
}
const char *sendMsg = "Hello, I'm Server";
send(clientSock, sendMsg, strlen(sendMsg), 0);
closesocket(clientSock);
}
}
// 关闭服务器socket
closesocket(servSock);
WSACleanup();
system("pause");
return 0;
}
客户端程序
程序实现的流程大致如下:
- 加载winsock动态库
- 初始化winsock
- 创建socket变量,并设置协议,IP和端口
- 发起连接
- 发送和接收数据
- 关闭socket
#include
#include
#include
#pragma comment(lib, "ws2_32.lib") //引入动态链接库
using namespace std;
#define SERVER_IP "192.168.1.109" // 服务器IP地址
int main()
{
SOCKET clientSock;
SOCKADDR_IN servAddr;
char buf[100];
int connect_status;
int send_status;
int recv_status;
WORD ws_version = MAKEWORD(2, 2); //指定Winsock version
WSADATA wsaData; //WSA 函数的参数
// 初始化winsock
if (WSAStartup(ws_version, &wsaData) != 0)
{
cout << "WSAStartup() error" << endl;
return -1;
}
while(true)
{
// 创建socket
clientSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (clientSock == INVALID_SOCKET)
{
cout << " socket creation error" << endl;
return -1;
}
servAddr.sin_family = AF_INET; //协议
servAddr.sin_port = htons(5050); //端口
//addr_server.sin_addr.s_addr = inet_addr(SERVER_IP);
inet_pton(AF_INET, SERVER_IP, &servAddr.sin_addr);
// 发起连接
connect_status = connect(clientSock, (SOCKADDR*)&servAddr, sizeof(SOCKADDR));
if(connect_status == 0)//连接成功
{
printf("\nConnecting... done\n");
//scanf("%s", buf);
cin >> buf;
//向服务端发送消息
send_status = send(clientSock, buf, 20, 0);
if(send_status == SOCKET_ERROR)//发送失败
{
printf("send error!\n");
}
else
{
printf("发送:%s\n", buf);
//接受服务端消息
recv_status = recv(clientSock, buf, 100, 0);
buf[recv_status] = '\0';
printf("收到:%s\n", buf);
}
}
else
{
printf("Test:fail to connect server! \n");
}
closesocket(clientSock);
}
WSACleanup();
return 0;
}