目录
前言
一、TCP_Server.cpp
二、TCP_Client.cpp
三、TCP Server.cpp (多线程)
总结
系列博客
【C/C++套接字编程】套接字的基本概念与基础语法_Mr_Fmnwon的博客-CSDN博客
【C/C++套接字编程】TCP通信实验_Mr_Fmnwon的博客-CSDN博客
【C/C++套接字编程】UDP协议通信的简单实现_Mr_Fmnwon的博客-CSDN博客
【C/C++套接字编程】UDP通信实验_Mr_Fmnwon的博客-CSDN博客
前言
本篇着重于基于socket编程,实现基本的TCP通信。
参考文献
C++实现TCP服务器端同时和多个客户端通信(多线程)_多客户端 tcp通信 c++_新西兰做的饭的博客-CSDN博客
一、TCP_Server.cpp
//server.cpp
#include <stdio.h>
#include <Winsock2.h>
#include <time.h>
#include <string.h>
#pragma warning(disable : 4996)
#pragma comment(lib, "ws2_32.lib")
#define USER_ERROR -1
using namespace std;
void space2_(char *str);
void print_time();
void print_time(in_addr addr);
//用于交互
void interactive(SOCKET socket_of_client,struct sockaddr_in c_sin);
int main()
{
WSADATA wsaData;
// 打开网络库/启动网络库,启动了这个库,这个库里的函数/功能才能使用
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
{
printf("Failed to load Winsock.\\n");
return USER_ERROR;
}
SOCKET socket_of_server;
SOCKET socket_of_client;
//part1 创建socket
socket_of_server = socket(AF_INET, SOCK_STREAM, 0);
//part1 end
// 确保socker创建成功
if (socket_of_server == INVALID_SOCKET)
{
printf("socket() Failed:%d\\n", WSAGetLastError());
return USER_ERROR;
}
//part2 填写套接字信息
struct sockaddr_in s_sin;
s_sin.sin_family = AF_INET;
s_sin.sin_port = htons(20000);
s_sin.sin_addr.S_un.S_addr =inet_addr("127.0.0.1");
//part2 end
//part3 将服务器的socket和服务器的ip地址和端口号绑定
if (bind(socket_of_server, (struct sockaddr *)&s_sin, sizeof(s_sin)) == SOCKET_ERROR)
{
printf("blind() Failed:%d\\n", WSAGetLastError());
return USER_ERROR;
}
//part4 启动监听
if (listen(socket_of_server,3) == SOCKET_ERROR)
//part4 end
{
print_time();
printf("listen() Failed:%d\\n", WSAGetLastError());
return USER_ERROR;
}
struct sockaddr_in c_sin;
int c_sin_len = sizeof(struct sockaddr_in);
// 不断监听,直到接收到客户端的连接
printf("==========Waiting for connect...==========\\n");
while (1)
{
//part5 建立tcp连接
socket_of_client = accept(socket_of_server, (struct sockaddr *)&c_sin, &c_sin_len);
//part5 end
if (socket_of_client == INVALID_SOCKET)
{
printf("accept() Failed:%d", WSAGetLastError());
print_time();
}
else
{
interactive(socket_of_client,c_sin);
}
}
closesocket(socket_of_server);
WSACleanup();
return 0;
}
void space2_(char *str)
{
for(unsigned int i=0; i<strlen(str); i++)
{
if(str[i] == ' ')
{
str[i] = '_';
}
}
}
void print_time(){
time_t cur_time;
time(&cur_time);
char *now=ctime(&cur_time);
now[24]='\\0';
printf("[%s]",now);
}
void print_time(in_addr addr){
time_t cur_time;
time(&cur_time);
char *now=ctime(&cur_time);
now[24]='\\0';
printf("[%s](From %s):",now,inet_ntoa(addr));
}
void interactive(SOCKET socket_of_client,struct sockaddr_in c_sin)
{
// int c_sin_len = sizeof(struct sockaddr_in);
char recvData[200];
char sendData[200];
print_time();
printf("接收到一个连接:%s\\r\\n", inet_ntoa(c_sin.sin_addr));
while (1)
{
recvData[0] = '\\0';
//part6 读取消息
int ret = recv(socket_of_client,recvData, 199, 0);
//part6 end
if (ret < 0)
{
print_time();
printf("***Something wrong***\\n");
continue;
}
recvData[ret] = '\\0';
// 如果客户端发送了quit,那么就退出
if (strcmp(recvData, "quit") == 0)
break;
print_time(c_sin.sin_addr);
printf("读取消息:");
printf("%s\\n", recvData);
printf("请发送消息:");
gets(sendData);
// space2_(sendData);
print_time();
printf("发送消息:%s",sendData);
printf("\\n");
//part7 发送消息
send(socket_of_client, sendData, 199, 0);
//part7 end
if (strcmp("quit", sendData) == 0)
break;
}
}
二、TCP_Client.cpp
//client.cpp
#include <winsock2.h>
#include <time.h>
#include <stdio.h>
#include <string.h>
#include <direct.h>
#include <time.h>
#pragma comment(lib, "ws2_32.lib")
#pragma warning(disable : 4996)
#define USER_ERROR -1
void delete_last_line();
void print_time();
void print_time_from(in_addr addr);
void print_time_to(in_addr addr);
int main()
{
// time_t now;
// char* curr_time = time(&now);
char recvData[200];
char sendData[200];
int ret;
//启动套接字编程,不启动无法运行相关API
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
{
printf("Failed to load Winsock.\\n");
return USER_ERROR;
}
//part1 创建套接字
SOCKET socket_client = socket(AF_INET, SOCK_STREAM, 0);
//end part1
if (socket_client == INVALID_SOCKET)
{
printf(" Failed socket() \\n");
return 0;
}
//part2 设置套接字信息 这里是需要
struct sockaddr_in server_in;
server_in.sin_family =AF_INET;
server_in.sin_port =htons(20000);
server_in.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
//part2 end
printf("=============Trying to connect...=============\\n");
//part3 连接服务器
if (connect(socket_client, (struct sockaddr *)&server_in, sizeof(server_in)) == -1)
//part3 end
{
printf(" Failed connect() \\n");
return 0;
}
else
{
print_time();
printf("connect %s.%d\\n", inet_ntoa(server_in.sin_addr),server_in.sin_port);
while (1)
{
memset(recvData,'\\0',sizeof(recvData));
memset(sendData,'\\0',sizeof(sendData));
printf("请发送消息:");
gets(sendData);
delete_last_line();
print_time_to(server_in.sin_addr);
printf("发送消息:【%s】\\n", sendData);
//part4 发送消息
send(socket_client, sendData, strlen(sendData), 0);
//part4 end
if (strcmp(sendData, "quit") == 0)
break;
recvData[0] = '\\0';
//part5 接收消息
ret = recv(socket_client, recvData, 200, 0);
recvData[ret] = '\\0';
print_time_from(server_in.sin_addr);
printf("读取消息:");
//part5 end
printf("%s\\n", recvData);
}
}
closesocket(socket_client);
WSACleanup();
return 0;
}
void delete_last_line()
{
printf("\\033[1A"); //先回到上一行
printf("\\033[K"); //清除该行
printf("\\r \\r");
}
void print_time() {
time_t cur_time;
time(&cur_time);
char* now = ctime(&cur_time);
now[24] = '\\0';
printf("[%s]", now);
}
void print_time_from(in_addr addr) {
time_t cur_time;
time(&cur_time);
char* now = ctime(&cur_time);
now[24] = '\\0';
printf("[%s](From %s):", now, inet_ntoa(addr));
}
void print_time_to(in_addr addr) {
time_t cur_time;
time(&cur_time);
char* now = ctime(&cur_time);
now[24] = '\\0';
printf("[%s](To %s):", now, inet_ntoa(addr));
}
三、TCP Server.cpp (多线程)
C++实现TCP服务器端同时和多个客户端通信(多线程)_多客户端 tcp通信 c++_新西兰做的饭的博客-CSDN博客
我们实现了两台机子的互相通信,能不能实现多个机子之间的互相通信呢?仔细想想,这就涉及到同时干多件事情的操作了。因此需要开多线程进行程序的处理。上面参考的博客,也是关于多线程实现服务器和多个客户端通信。(这里的多线程实现了多个用户端和服务端的通信,但是并没有完全完善,存在着服务端需要依次和多个用户端通信的情况,而交互界面也尚待完善)文章来源:https://www.toymoban.com/news/detail-489168.html
//server.cpp
#include <stdio.h>
#include <Winsock2.h>
#include <time.h>
#include <string.h>
#include <thread>
#include <iostream>
#pragma warning(disable : 4996)
#pragma comment(lib, "ws2_32.lib")
#define USER_ERROR -1
using namespace std;
void space2_(char* str);
void print_time();
void print_time_from(in_addr addr);
void print_time_to(in_addr addr);
bool GetAddressBySocket(SOCKET m_socket, SOCKADDR_IN& m_address);
void delete_last_line();
//用于交互
DWORD WINAPI interactive(LPVOID lpThreadParameter);
int main()
{
WSADATA wsaData;
// 打开网络库/启动网络库,启动了这个库,这个库里的函数/功能才能使用
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
{
printf("Failed to load Winsock.\\n");
return USER_ERROR;
}
SOCKET socket_of_server;
SOCKET socket_of_client;
//part1 创建socket
socket_of_server = socket(AF_INET, SOCK_STREAM, 0);
//part1 end
// 确保socker创建成功
if (socket_of_server == INVALID_SOCKET)
{
printf("socket() Failed:%d\\n", WSAGetLastError());
return USER_ERROR;
}
//part2 填写套接字信息
struct sockaddr_in s_sin;
s_sin.sin_family = AF_INET;
s_sin.sin_port = htons(20000);
s_sin.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
//part2 end
//part3 将服务器的socket和服务器的ip地址和端口号绑定
if (bind(socket_of_server, (struct sockaddr*)&s_sin, sizeof(s_sin)) == SOCKET_ERROR)
{
printf("blind() Failed:%d\\n", WSAGetLastError());
return USER_ERROR;
}
//part4 启动监听
if (listen(socket_of_server, 3) == SOCKET_ERROR)
//part4 end
{
print_time();
printf("listen() Failed:%d\\n", WSAGetLastError());
return USER_ERROR;
}
struct sockaddr_in c_sin;
int c_sin_len = sizeof(struct sockaddr_in);
// 不断监听,直到接收到客户端的连接
printf("==========Waiting for connect...==========\\n");
while (1)
{
//part5 建立tcp连接
socket_of_client = accept(socket_of_server, (struct sockaddr*)&c_sin, &c_sin_len);
//part5 end
if (socket_of_client == INVALID_SOCKET)
{
printf("accept() Failed:%d", WSAGetLastError());
print_time();
}
else
{
HANDLE hThread = CreateThread(NULL, 0, interactive, (LPVOID)socket_of_client, 0,NULL);
}
}
closesocket(socket_of_server);
WSACleanup();
return 0;
}
void space2_(char* str)
{
for (auto i = 0; i < strlen(str); i++)
{
if (str[i] == ' ')
{
str[i] = '_';
}
}
}
void print_time() {
time_t cur_time;
time(&cur_time);
char* now = ctime(&cur_time);
now[24] = '\\0';
printf("[%s]", now);
}
void print_time_from(in_addr addr) {
time_t cur_time;
time(&cur_time);
char* now = ctime(&cur_time);
now[24] = '\\0';
printf("[%s](From %s):", now, inet_ntoa(addr));
}
void print_time_to(in_addr addr) {
time_t cur_time;
time(&cur_time);
char* now = ctime(&cur_time);
now[24] = '\\0';
printf("[%s](To %s):", now, inet_ntoa(addr));
}
DWORD WINAPI interactive(LPVOID lpThreadParameter)
{
char recvData[200];
char sendData[200];
SOCKADDR_IN c_sin;
print_time();
SOCKET socket_of_client = (SOCKET)lpThreadParameter;
GetAddressBySocket(socket_of_client,c_sin);
printf("接收到一个连接:IP(%s)Port(%d)\\r\\n", inet_ntoa(c_sin.sin_addr), ntohs(c_sin.sin_port));
while (1)
{
recvData[0] = '\\0';
//part6 读取消息
int ret = recv(socket_of_client, recvData, 199, 0);
//part6 end
if (ret < 0)
{
//m.lock();
print_time();
printf("***Something wrong***\\n");
//m.unlock();
continue;
}
recvData[ret] = '\\0';
// 如果客户端发送了quit,那么就退出
if (strcmp(recvData, "quit") == 0)
break;
//m.lock();
print_time_from(c_sin.sin_addr);
printf("读取消息:【%s】\\n",recvData);
//printf("%s\\n", recvData);
printf("请发送消息:");
gets_s(sendData);
// space2_(sendData);
delete_last_line();
print_time_to(c_sin.sin_addr);
printf("发送消息:【%s】\\n", sendData);
//printf("\\n");
//m.unlock();
//part7 发送消息
send(socket_of_client, sendData, 199, 0);
//part7 end
if (strcmp("quit", sendData) == 0)
break;
}
}
//通过套接字获取IP、Port等地址信息
bool GetAddressBySocket(SOCKET m_socket, SOCKADDR_IN& m_address)
{
memset(&m_address, 0,sizeof(m_address));
int nAddrLen = sizeof(m_address);
//根据套接字获取地址信息
if (::getpeername(m_socket, (SOCKADDR*)&m_address, &nAddrLen) != 0)
{
//printf("Get IP address by socket Failed!n");
return false;
}
//读取IP和Port
//cout << "IP: " << ::inet_ntoa(m_address.sin_addr) << " PORT: " << ntohs(m_address.sin_port) << endl;
return true;
}
void delete_last_line()
{
printf("\\033[1A"); //先回到上一行
printf("\\033[K"); //清除该行
printf("\\r \\r");
}
总结
关于TCP通信的相关过程与细节,还需要加深理解文章来源地址https://www.toymoban.com/news/detail-489168.html
到了这里,关于【C/C++套接字编程】TCP协议通信的简单实现的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!