控制台命令状态运行的TCP通信服务器及客户机程序,实现简单的数据传输功能

控制台命令状态运行的TCP通信服务器及客户机程序,实现简单的数据传输功能

采用vs2019控制台应用实现
客户机部分
//客户机main函数
#include <stdio.h>
#include "CComm.h"
int main(int argc, char* argv[])
{
	char buffer[4096];	//输入缓冲区		
	char* desthost;    //服务器ip地址
	short destport;	  // 服务器端口号
	// 确保输入正确
	if (argc != 3 || !(destport = atoi(argv[2])) || !(desthost = argv[1]))
	{
		printf("输入正确的服务器IP地址和端口号\n");
		return 0;
	}

	CComm myComm;
	if (!myComm.Listen(desthost,destport))	// 连接到服务器地址
	{
		printf("连接失败\n");
		return 0;
	}
	while (fgets(buffer, sizeof(buffer), stdin))	// 获得输入数据
	{
		myComm.SendMsg(buffer, strlen(buffer));	// 发送数据到服务器
	}
	return 0;
}

//CComm.h
#pragma once
#include <string.h>
#include<stdio.h>
#include<stdlib.h>
#include<winsock.h>
#define socklen_t int;
#pragma comment(lib,"wsock32.lib")
class CComm
{
private:
	
	static void* ListenThread(void* data);
	SOCKET ClientSocket;  //等待接收数据的socket
	sockaddr_in srv;      //绑定地址
public:
	CComm();
	~CComm();
    bool Listen(char * addr,int PortNum);
	bool SendMsg(char* Msg, int Len);		 
};
//CComm.cpp
#include "CComm.h"
CComm::CComm()
{
	//构造函数
	ClientSocket = INVALID_SOCKET;	// 开始设置为INVALID_SOCKET

#ifdef _WIN32	// 如果是win32系统
	WORD VersionRequested = MAKEWORD(1, 1);
	WSADATA wsaData;

	WSAStartup(VersionRequested, &wsaData);	// 启动winsock服务
	if (wsaData.wVersion != VersionRequested)
	{
		printf("Wrong version or WinSock not loaded\n");
		fflush(0);
	}
#endif
}
CComm::~CComm()
{//析构函数
	if (ClientSocket != INVALID_SOCKET)
		closesocket(ClientSocket);	// 如果已经创建、则关闭

#ifdef _WIN32	// 调用WSACleanup
	WSACleanup();
#endif
}
bool CComm::SendMsg(char* Msg, int Len)//向服务器发送数据
{
	signed int Sent;
	Sent = send(ClientSocket, Msg, Len, 0);
	if (Sent != Len)
	{
		printf("发送失败 \n");
		fflush(0);
		return false;
	}
	return true;
}
bool CComm::Listen(char* addr,int PortNum)
{
	ClientSocket = socket(PF_INET, SOCK_STREAM, 0);
	if (ClientSocket == INVALID_SOCKET)
	{
		printf("socket创建失败\n");
		fflush(0);
		return false;
	}

	srv.sin_family = PF_INET;
	srv.sin_addr.S_un.S_addr= inet_addr(addr);//TCP客户端需要有确切的地址
	srv.sin_port = htons(PortNum);//字节顺序转换
	if (connect(ClientSocket, (struct sockaddr*) &srv, sizeof(sockaddr)) != 0)
	{
		printf("连接失败\n");
		fflush(0);
		closesocket(ClientSocket);
		return false;
	}
	else {
		char sendbuf[1024],hostname[100];
		gethostname(hostname,100);//获得主机名称
		sprintf_s(sendbuf, "%s 已连接!", hostname);
		send(ClientSocket, sendbuf, strlen(sendbuf) + 1, 0);

	}
	int ThreadID;	// 线程id

	DWORD thread;
	//调用createthread创建线程
	ThreadID = (int)CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)(CComm::ListenThread), (void*)this, 0, &thread);
	ThreadID = ThreadID ? 0 : 1;	// 如果成功,则返回为0

	if (ThreadID)	// ThreadID如果不为0,则线程创建失败
	{
		printf("线程创建失败\n");
		return false;
	}
	else
		return true;
}
void* CComm::ListenThread(void* data)
{
	char buf[4096];
	CComm* Comm = (CComm*)data;
	bool flag = true;
	while (1)	// 一直循环
	{
		//接收数据 
		int result = recv(Comm->ClientSocket, buf, sizeof(buf) - 1, 0);
		
		if (result > 0)
		{
			buf[result] = 0;
			if (flag) {
				printf("%s \n", buf);
				flag = false;
			}
			else{
			printf("Message received from host %s port %i\n", inet_ntoa(Comm->srv.sin_addr), ntohs(Comm->srv.sin_port));
			printf(">>%s", buf);
			fflush(0);
			}
		}
	}
}
服务器部分
//服务器main函数
#pragma once
#include <string.h>
#include<stdio.h>
#include<stdlib.h>
#include<winsock.h>
#define socklen_t int;
#pragma comment(lib,"wsock32.lib")
class CComm
{
private:
	static void* ListenThread(void* data);
	SOCKET ListenSocket;  //等待接收数据的socket
	sockaddr_in srv;      //绑定地址
	sockaddr_in client;  //发送数据过来的地址
public:
	CComm();
	~CComm();

	bool SendMsg(char* Msg, int Len);
	bool Listen(int PortNum);


};
//CComm.h
#pragma once
#include <string.h>
#include<stdio.h>
#include<stdlib.h>
#include<winsock.h>
#define socklen_t int;
#pragma comment(lib,"wsock32.lib")
class CComm
{
private:
	static void* ListenThread(void* data);
	SOCKET ListenSocket;  //等待接收数据的socket
	sockaddr_in srv;      //绑定地址
	sockaddr_in client;  //发送数据过来的地址
public:
	CComm();
	~CComm();

	bool SendMsg(char* Msg, int Len);
	bool Listen(int PortNum);


};
CComm.cpp
#include "CComm.h"
CComm::CComm()
{
	//构造函数
	ListenSocket = INVALID_SOCKET;	// 开始设置为INVALID_SOCKET

#ifdef _WIN32	// 如果是win32系统
	WORD VersionRequested = MAKEWORD(1, 1);
	WSADATA wsaData;

	WSAStartup(VersionRequested, &wsaData);	// 启动winsock服务
	if (wsaData.wVersion != VersionRequested)
	{
		printf("Wrong version or WinSock not loaded\n");
		fflush(0);
	}
#endif
}
CComm::~CComm()
{//析构函数
	if (ListenSocket != INVALID_SOCKET)
		closesocket(ListenSocket);	// 如果已经创建、则关闭

#ifdef _WIN32	// 调用WSACleanup
	WSACleanup();
#endif
}
bool CComm::SendMsg(char* Msg, int Len)
{
	signed int Sent;	
	//数据发送
	Sent = send(ListenSocket, Msg, Len, 0);
	if (Sent != Len)
	{
		printf("Error: failed to send udp message! \n");
		fflush(0);
		return false;
	}
	return true;
}
bool CComm::Listen(int PortNum)
{
	ListenSocket = socket(PF_INET, SOCK_STREAM, 0);
	if (ListenSocket == INVALID_SOCKET)
	{
		printf("Error: socket创建失败\n");
		fflush(0);
		return false;
	}

	srv.sin_family = PF_INET;
	srv.sin_addr.s_addr = htonl(INADDR_ANY);	// 任何地址
	srv.sin_port = htons(PortNum);

	if (bind(ListenSocket, (struct sockaddr*) & srv, sizeof(sockaddr)) != 0)
	{
		printf("绑定失败\n");
		fflush(0);
		closesocket(ListenSocket);
		return false;
	}
	if (listen(ListenSocket, 10)!= 0) {
		printf("%d", WSAGetLastError());
		printf("侦听失败\n");
		fflush(0);
		closesocket(ListenSocket);
		return false;
	}
	else {
		printf("服务器已打开。\n正在等待客户端接入.......\n");
	}
	int len = sizeof(SOCKADDR);
	ListenSocket = accept(ListenSocket, (struct sockaddr*) &client, &len);
	if (ListenSocket == INVALID_SOCKET) {
		printf("接受失败\n");
		fflush(0);
		closesocket(ListenSocket);
		return false;
	}	
	else {
		char  hostname[100], sendbuf[1024];
		gethostname(hostname, 100);
		sprintf_s(sendbuf, "欢迎 %s 连接到 %s!", inet_ntoa(client.sin_addr), hostname);
		send(ListenSocket, sendbuf, strlen(sendbuf) + 1, 0);
	}
	int ThreadID;	// 线程id

	DWORD thread;
	//调用createthread创建线程
	ThreadID = (int)CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)(CComm::ListenThread), (void*)this, 0, &thread);
	ThreadID = ThreadID ? 0 : 1;	// 如果成功,则返回为0

	if (ThreadID)	// ThreadID如果不为0,则线程创建失败
	{
		printf("线程创建失败\n");
		return false;
	}
	else
		return true;
}
void* CComm::ListenThread(void* data)
{
	char buf[4096];
	CComm* Comm = (CComm*)data;
	int len = sizeof(Comm->client);
	 bool flag = true;
	while (1)	// 一直循环
	{
		//接收数据
		int result = recv(Comm->ListenSocket, buf, sizeof(buf) - 1, 0);
		if (result > 0)
		{
			buf[result] = 0;
			if (flag) {
				printf("%s \n", buf);
				flag = false;
			}
			else{
			printf("Message received from host %s port %i\n", inet_ntoa(Comm->client.sin_addr), ntohs(Comm->client.sin_port));
			printf(">>%s", buf);
			fflush(0);
			}
		}
	}
}

若想在VS上直接运行需要修改属性页配置属性调试中的命令参数,如在客户机中输入对方IP地址及对方用来侦听的端口号,而在服务器中输入用来侦听的端口号。
在这里插入图片描述
也可直接在cmd中直接运行debug中的exe文件,也要把相应的参数写在后面。如运行服务器代码先找到对应的exe文件所在的位置输入"服务器.exe 1000"。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xy浅

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值