可以在windows上面使用!
服务端:
/*
* @Description:SOCKET
* @Author: szq
* @Github: https://github.com/MrQqqq
* @Date: 2020-06-26 00:04:39
* @LastEditors: szq
* @LastEditTime: 2020-06-26 00:04:39
* @FilePath: \cpp\src\BinaryTree\client_TCp.cpp
*/
#include
#include
#include
#pragma comment(lib,"ws2_32.lib")
using namespace std;
void initialization() {
//初始化套接字库
WORD w_req = MAKEWORD(2, 2);//版本号
WSADATA wsadata;
int err;
err = WSAStartup(w_req, &wsadata);
if (err != 0) {
cout << "初始化套接字库失败!" << endl;
}
else {
cout << "初始化套接字库成功!" << endl;
}
//检测版本号
if (LOBYTE(wsadata.wVersion) != 2 || HIBYTE(wsadata.wHighVersion) != 2) {
cout << "套接字库版本号不符!" << endl;
WSACleanup();
}
else {
cout << "套接字库版本正确!" << endl;
}
}
enum MyCMD {
LOGIN,
LOGOUT,
LOGERROR,
RESULT
};
class DataHeader {
public:
int dataLength;
MyCMD cmd;
};
class Login : public DataHeader{
public:
Login() {
dataLength = sizeof(Login);
cmd = LOGIN;
}
char username[30];
char password[30];
};
class Result : public DataHeader {
public:
int result;
Result(int a) {
dataLength = sizeof(Result);
cmd = RESULT;
result = a;
}
};
vector<SOCKET> g_clients;
int main() {
//定义长度变量
int send_len = 0;
int recv_len = 0;
int len = 0;
//定义发送缓冲区和接收缓冲区
char send_buf[1024];
char recv_buf[1024];
//定义服务器套接字,接受请求套接字
SOCKET s_server;
//服务器地址和客户端地址
SOCKADDR_IN server_addr;
initialization();
//填充服务端信息
server_addr.sin_family = AF_INET;
server_addr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
server_addr.sin_port = htons(5010);
//创建套接字
s_server = socket(AF_INET, SOCK_STREAM, 0);
if (bind(s_server, (SOCKADDR*)&server_addr, sizeof(SOCKADDR)) == SOCKET_ERROR) {
cout << "套接字绑定失败!" << endl;
}
else {
cout << "套接字绑定成功!" << endl;
}
if (listen(s_server, SOMAXCONN) < 0) {
cout << "设置监听状态失败!" << endl;
}
else {
cout << "设置监听状态成功!" << endl;
}
cout << "服务器正在监听连接,请稍候..." << endl;
while (1) {
fd_set fdRead;
fd_set fdWrite;
fd_set fdExecpt;
//清空
FD_ZERO(&fdRead);
FD_ZERO(&fdWrite);
FD_ZERO(&fdExecpt);
FD_SET(s_server, &fdRead);
FD_SET(s_server, &fdWrite);
FD_SET(s_server, &fdExecpt);
for (int i = 0; i < g_clients.size(); i++) {
FD_SET(g_clients[i], &fdRead);
}
//nfds是一个整数值,是指fd_set集合中所有描述符的范围,而不是数量,即最大值
timeval t = {
0,0 };//设置成非阻塞
int ret = select(s_server + 1, &fdRead, &fdWrite, &fdExecpt,&t);
if (ret < 0) {
cout << "select任务结束!" << endl;
break;
}
if (FD_ISSET(s_server, &fdRead)) {
FD_CLR(s_server, &fdRead);
SOCKET s_accept = INVALID_SOCKET;
SOCKADDR_IN accept_addr;
len = sizeof(SOCKADDR);
s_accept = accept(s_server, (SOCKADDR*)&accept_addr, &len);
if (s_accept == SOCKET_ERROR) {
cout << "连接失败!" << endl;
return 0;
}
cout << "连接建立,准备接受数据" << endl;
g_clients.push_back(s_accept);
}
for (int i = 0; i < fdRead.fd_count; i++) {
//处理
recv_len = recv(fdRead.fd_array[i], recv_buf, 1024, 0);
if (recv_len < 0) {
cout << "接受失败!" << endl;
auto iter = find(g_clients.begin(), g_clients.end(), fdRead.fd_array[i]);
g_clients.erase(iter);
break;
}
else {
Login *login = (Login*)recv_buf;
if (login->cmd == LOGIN) {
if (strcmp(login->username, "szq") == 0) {
Result result(1);
send_len = send(g_clients[i], (char*)&result, sizeof(Result), 0);
}
cout << "登录信息: 用户名=" << login->username << " 密码=" << login->password << endl;
if (send_len < 0) {
cout << "发送失败!" << endl;
break;
}
}
}
}
}
//关闭套接字
closesocket(s_server);
for (auto skt : g_clients) {
closesocket(skt);
}
return 0;
}
客户端:
#include
#include
#include
#pragma comment(lib,"ws2_32.lib")
#pragma warning( disable : 4996)
using namespace std;
void initialization();
enum MyCMD {
LOGIN,
LOGOUT,
LOGERROR,
RESULT
};
class DataHeader {
public:
int dataLength;
MyCMD cmd;
};
class Login : public DataHeader {
public:
Login() {
dataLength = sizeof(Login);
cmd = LOGIN;
}
char username[30];
char password[30];
};
class Result : public DataHeader {
public:
int result;
Result(int a) {
dataLength = sizeof(Result);
cmd = RESULT;
result = a;
}
};
int main() {
//定义长度变量
int send_len = 0;
int recv_len = 0;
//定义发送缓冲区和接受缓冲区
char send_buf[100];
char recv_buf[100];
//定义服务端套接字,接受请求套接字
SOCKET s_server;
//服务端地址客户端地址
SOCKADDR_IN server_addr;
initialization();
//填充服务端信息
server_addr.sin_family = AF_INET;
server_addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
server_addr.sin_port = htons(5010);
//创建套接字
s_server = socket(AF_INET, SOCK_STREAM, 0);
if (connect(s_server, (SOCKADDR *)&server_addr, sizeof(SOCKADDR)) == SOCKET_ERROR) {
cout << "服务器连接失败!" << endl;
WSACleanup();
}
else {
cout << "服务器连接成功!" << endl;
}
//发送,接收数据
while (1) {
char s[30];
cin >> s;
if (strcmp(s,"login") != 0) {
continue;
}
Login login;
strcpy(login.username, "szq");
strcpy(login.password, "123");
send_len = send(s_server, (char*)&login, sizeof(login), 0);
if (send_len < 0) {
cout << "发送失败!" << endl;
break;
}
recv_len = recv(s_server, recv_buf, 100, 0);
if (recv_len < 0) {
cout << "接受失败!" << endl;
break;
}
else {
Result *result = (Result*)recv_buf;
cout << "登录结果为:" << result->result << endl;
}
}
//关闭套接字
closesocket(s_server);
//释放DLL资源
WSACleanup();
return 0;
}
void initialization() {
//初始化套接字库
WORD w_req = MAKEWORD(2, 2);//版本号
WSADATA wsadata;
int err;
err = WSAStartup(w_req, &wsadata);
if (err != 0) {
cout << "初始化套接字库失败!" << endl;
}
else {
cout << "初始化套接字库成功!" << endl;
}
//检测版本号
if (LOBYTE(wsadata.wVersion) != 2 || HIBYTE(wsadata.wHighVersion) != 2) {
cout << "套接字库版本号不符!" << endl;
WSACleanup();
}
else {
cout << "套接字库版本正确!" << endl;
}
//填充服务端地址信息
}
版本2:可以支持跨平台的版本。
服务端
/*
* @Description:SOCKET
* @Author: szq
* @Github: https://github.com/MrQqqq
* @Date: 2020-06-26 00:04:39
* @LastEditors: szq
* @LastEditTime: 2020-06-26 00:04:39
* @FilePath: \cpp\src\BinaryTree\client_TCp.cpp
*/
#include
#include
#ifdef _WIN32
#include
#pragma comment(lib,"ws2_32.lib")
#else
#include
#include
#include
#include
#include
#define SOCKET int
#define SOCKADDR_IN sockaddr_in
#define SOCKADDR sockaddr
#define SOCKET_ERROR socket_error
#endif
using namespace std;
void initialization() {
#ifdef _WIN32
//初始化套接字库
WORD w_req = MAKEWORD(2, 2);//版本号
WSADATA wsadata;
int err;
err = WSAStartup(w_req, &wsadata);
if (err != 0) {
cout << "初始化套接字库失败!" << endl;
}
else {
cout << "初始化套接字库成功!" << endl;
}
//检测版本号
if (LOBYTE(wsadata.wVersion) != 2 || HIBYTE(wsadata.wHighVersion) != 2) {
cout << "套接字库版本号不符!" << endl;
WSACleanup();
}
else {
cout << "套接字库版本正确!" << endl;
}
#endif
}
enum MyCMD {
LOGIN,
LOGOUT,
LOGERROR,
RESULT
};
class DataHeader {
public:
int dataLength;
MyCMD cmd;
};
class Login : public DataHeader{
public:
Login() {
dataLength = sizeof(Login);
cmd = LOGIN;
}
char username[30];
char password[30];
};
class Result : public DataHeader {
public:
int result;
Result(int a) {
dataLength = sizeof(Result);
cmd = RESULT;
result = a;
}
};
vector<SOCKET> g_clients;
int main() {
//定义长度变量
int send_len = 0;
int recv_len = 0;
unsigned int len = 0;
//定义发送缓冲区和接收缓冲区
char send_buf[1024];
char recv_buf[1024];
//定义服务器套接字,接受请求套接字
SOCKET s_server;
//服务器地址和客户端地址
SOCKADDR_IN server_addr;
initialization();
//填充服务端信息
server_addr.sin_family = AF_INET;
#ifdef _WIN32
server_addr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
#else
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
#endif
server_addr.sin_port = htons(5010);
//创建套接字
s_server = socket(AF_INET, SOCK_STREAM, 0);
if (bind(s_server, (SOCKADDR*)&server_addr, sizeof(SOCKADDR)) < 0) {
cout << "套接字绑定失败!" << endl;
}
else {
cout << "套接字绑定成功!" << endl;
}
if (listen(s_server, SOMAXCONN) < 0) {
cout << "设置监听状态失败!" << endl;
}
else {
cout << "设置监听状态成功!" << endl;
}
cout << "服务器正在监听连接,请稍候..." << endl;
while (1) {
fd_set fdRead;
fd_set fdWrite;
fd_set fdExecpt;
//清空
FD_ZERO(&fdRead);
FD_ZERO(&fdWrite);
FD_ZERO(&fdExecpt);
FD_SET(s_server, &fdRead);
FD_SET(s_server, &fdWrite);
FD_SET(s_server, &fdExecpt);
for (int i = 0; i < g_clients.size(); i++) {
FD_SET(g_clients[i], &fdRead);
}
//nfds是一个整数值,是指fd_set集合中所有描述符的范围,而不是数量,即最大值
timeval t = {
0,0 };//设置成非阻塞
int ret = select(s_server + 1, &fdRead, &fdWrite, &fdExecpt,&t);
if (ret < 0) {
cout << "select任务结束!" << endl;
break;
}
if (FD_ISSET(s_server, &fdRead)) {
FD_CLR(s_server, &fdRead);
SOCKET s_accept = 0;
SOCKADDR_IN accept_addr;
len = sizeof(SOCKADDR);
s_accept = accept(s_server, (SOCKADDR*)&accept_addr, &len);
if (s_accept < 1) {
cout << "连接失败!" << endl;
return 0;
}
cout << "连接建立,准备接受数据" << endl;
g_clients.push_back(s_accept);
}
#ifdef _WIN32
for (int i = 0; i < fdRead.fd_count; i++) {
//处理
recv_len = recv(fdRead.fd_array[i], recv_buf, 1024, 0);
if (recv_len < 0) {
cout << "接受失败!" << endl;
auto iter = find(g_clients.begin(), g_clients.end(), fdRead.fd_array[i]);
g_clients.erase(iter);
break;
}
else {
Login *login = (Login*)recv_buf;
if (login->cmd == LOGIN) {
if (strcmp(login->username, "szq") == 0) {
Result result(1);
send_len = send(g_clients[i], (char*)&result, sizeof(Result), 0);
}
cout << "登录信息: 用户名=" << login->username << " 密码=" << login->password << endl;
if (send_len < 0) {
cout << "发送失败!" << endl;
break;
}
}
}
}
#else
/*
* 由于在Linux系统中FD_SET的定义不同,没有相应的fd_count和fd_array,因此这里遍历FD_SET的方式有所不同
*
* */
while(g_clients.size() > 0){
//处理
recv_len = recv(g_clients[0], recv_buf, 1024, 0);
if (recv_len < 0) {
cout << "接受失败!" << endl;
g_clients.erase(g_clients.begin());
}
else {
Login *login = (Login*)recv_buf;
if (login->cmd == LOGIN) {
if (strcmp(login->username, "szq") == 0) {
Result result(1);
send_len = send(g_clients[0], (char*)&result, sizeof(Result), 0);
}
cout << "登录信息: 用户名=" << login->username << " 密码=" << login->password << endl;
if (send_len < 0) {
cout << "发送失败!" << endl;
break;
}
}
}
}
#endif
}
//关闭套接字
#ifdef _WIN32
closesocket(s_server);
#else
close(s_server);
#endif
for (auto skt : g_clients) {
#ifdef _WIN32
closesocket(skt);
#else
close(skt);
#endif
}
return 0;
}
客户端:
#include
#include
#ifdef _WIN32
#include
#pragma comment(lib,"ws2_32.lib")
#else
#include
#include
#include
#include
#include
#include
#define SOCKET int
#define SOCKADDR_IN sockaddr_in
#define SOCKADDR sockaddr
#define SOCKET_ERROR 0
#endif
using namespace std;
void initialization() {
#ifdef _WIN32
//初始化套接字库
WORD w_req = MAKEWORD(2, 2);//版本号
WSADATA wsadata;
int err;
err = WSAStartup(w_req, &wsadata);
if (err != 0) {
cout << "初始化套接字库失败!" << endl;
}
else {
cout << "初始化套接字库成功!" << endl;
}
//检测版本号
if (LOBYTE(wsadata.wVersion) != 2 || HIBYTE(wsadata.wHighVersion) != 2) {
cout << "套接字库版本号不符!" << endl;
WSACleanup();
}
else {
cout << "套接字库版本正确!" << endl;
}
#endif
}
enum MyCMD {
LOGIN,
LOGOUT,
LOGERROR,
RESULT
};
class DataHeader {
public:
int dataLength;
MyCMD cmd;
};
class Login : public DataHeader {
public:
Login() {
dataLength = sizeof(Login);
cmd = LOGIN;
}
char username[30];
char password[30];
};
class Result : public DataHeader {
public:
int result;
Result(int a) {
dataLength = sizeof(Result);
cmd = RESULT;
result = a;
}
};
int main() {
//定义长度变量
int send_len = 0;
int recv_len = 0;
//定义发送缓冲区和接受缓冲区
char send_buf[100];
char recv_buf[100];
//定义服务端套接字,接受请求套接字
SOCKET s_server;
//服务端地址客户端地址
SOCKADDR_IN server_addr;
initialization();
//填充服务端信息
server_addr.sin_family = AF_INET;
#ifdef _WIN32
server_addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
#else
server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
#endif
server_addr.sin_port = htons(5010);
//创建套接字
s_server = socket(AF_INET, SOCK_STREAM, 0);
if (connect(s_server, (SOCKADDR *)&server_addr, sizeof(SOCKADDR)) < 0) {
cout << "服务器连接失败!" << endl;
#ifdef _WIN32
WSACleanup();
#endif
}
else {
cout << "服务器连接成功!" << endl;
}
//发送,接收数据
while (1) {
char s[30];
cin >> s;
if (strcmp(s,"login") != 0) {
continue;
}
Login login;
strcpy(login.username, "szq");
strcpy(login.password, "123");
send_len = send(s_server, (char*)&login, sizeof(login), 0);
if (send_len < 0) {
cout << "发送失败!" << endl;
break;
}
recv_len = recv(s_server, recv_buf, 100, 0);
if (recv_len < 0) {
cout << "接受失败!" << endl;
break;
}
else {
Result *result = (Result*)recv_buf;
cout << "登录结果为:" << result->result << endl;
}
}
//关闭套接字
#ifdef _WIN32
closesocket(s_server);
#else
close(s_server);
#endif
//释放DLL资源
#ifdef _WIN32
WSACleanup();
#endif
return 0;
}