首页 > 编程语言 >用Winsock编写服务端和客户端 (C++)

用Winsock编写服务端和客户端 (C++)

时间:2023-04-25 22:56:52浏览次数:48  
标签:ErrorHandling hSocket C++ Winsock argv 接字 message servAddr 服务端

   在这里先向大家推荐一本不错的入门书籍——《TCPIP网络编程》(尹圣雨 著),这本书比较贴近实战,是一本不错的网络编程方向的指导用书。如果需要PDF版本,可以后台私信我!

  回归正题,我们欲要使用C++实现一个简易的服务端和客户端控制台程序。代码如下:

   服务端:

/*****************************************************************************************************************************
*    服务端流程如下:
*	1、声明套接字库,创建套接字(WSAStartup()/socket());
*	2、绑定套接字到一个IP地址和一个端口上(bind());
*	3、将套接字设置为监听模式等待连接请求;
*	4、请求到来之后,接受连接请求,返回一个新的对应于此次连接的套接字(accept());
*	5、用返回的套接字和客户端进行通信(send()/recv());
*	6、返回,等待另一个连接请求
*	7、关闭套接字,关闭加载的套接字库(closesocket()/WSACleanup());
*****************************************************************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <winsock2.h> //一般基于套接字的编程引用这个库
void ErrorHandling(char* message);

int main(int argc, char* argv[])
{
	WSADATA wsaData;
	SOCKET hSocket; //SOCKET作为数据类型 声明一个套接字对象
	SOCKADDR_IN servAddr; //用于记录服务端地址

	char message[30]; //发送消息
	int strLen;

	if(argc!=3)
	{
		printf("Usage : %s <IP> <port>\n", argv[0]);
		exit(1);
	}

	if(WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
		ErrorHandling("WSAStartup() error!");  
	
	hSocket=socket(PF_INET, SOCK_STREAM, 0);
	if(hSocket==INVALID_SOCKET)
		ErrorHandling("socket() error");
	
	memset(&servAddr, 0, sizeof(servAddr));
	servAddr.sin_family=AF_INET;
	servAddr.sin_addr.s_addr=inet_addr(argv[1]);
	servAddr.sin_port=htons(atoi(argv[2]));
	
	if(connect(hSocket, (SOCKADDR*)&servAddr, sizeof(servAddr))==SOCKET_ERROR)
		ErrorHandling("connect() error!");
 
	strLen=recv(hSocket, message, sizeof(message)-1, 0);
	if(strLen==-1)
		ErrorHandling("read() error!");
	printf("Message from server: %s \n", message);  

	closesocket(hSocket); //用完后务必记住要关闭套接字
	WSACleanup(); //做一次清理
	return 0;
}

void ErrorHandling(char* message)
{
	fputs(message, stderr);
	fputc('\n', stderr);
	exit(1);
}

客户端:

/*****************************************************************************************************************************
*    客户端流程如下:
*    1:加载套接字库,创建套接字(WSAStartup()/socket());
*    2:向服务器发出连接请求(connect());
*    3:和服务器端进行通信(send()/recv());
*    4:关闭套接字,关闭加载的套接字库(closesocket()/WSACleanup())
*****************************************************************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <winsock2.h>
void ErrorHandling(char* message);

int main(int argc, char* argv[])
{
    //客户端与服务端有相似之处
	WSADATA wsaData;
	SOCKET hSocket;
	SOCKADDR_IN servAddr;

	char message[30];
	int strLen;

	if(argc!=3)
	{
		printf("Usage : %s <IP> <port>\n", argv[0]);
		exit(1);
	}

	if(WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
		ErrorHandling("WSAStartup() error!");  
	
	hSocket=socket(PF_INET, SOCK_STREAM, 0);
	if(hSocket==INVALID_SOCKET)
		ErrorHandling("socket() error");
	
	memset(&servAddr, 0, sizeof(servAddr));
	servAddr.sin_family=AF_INET;
	servAddr.sin_addr.s_addr=inet_addr(argv[1]); //配置地址
	servAddr.sin_port=htons(atoi(argv[2])); //配置端口号
	
	if(connect(hSocket, (SOCKADDR*)&servAddr, sizeof(servAddr))==SOCKET_ERROR)
		ErrorHandling("connect() error!");
 
	strLen=recv(hSocket, message, sizeof(message)-1, 0);
	if(strLen==-1)
		ErrorHandling("read() error!");
	printf("Message from server: %s \n", message);  

	closesocket(hSocket);
	WSACleanup();
	return 0;
}

void ErrorHandling(char* message)
{
	fputs(message, stderr);
	fputc('\n', stderr);
	exit(1);
}

  两个程序可以直接运行,在VS中调试时需要在解决方案中做成两个单独的项目,在启动调试时选中多个“启动项目”,如下图所示:

                                       

标签:ErrorHandling,hSocket,C++,Winsock,argv,接字,message,servAddr,服务端
From: https://www.cnblogs.com/MaxTsang/p/17354212.html

相关文章

  • C++第四章课后习题4-12
    定义一个datatype类,能处理包含字符型,整形,浮点型3种类型的数据,给出其构造函数。1#include<iostream>2usingnamespacestd;34classDataType{5private:6chara;7intn;8floatx;9enum{10character,11intege......
  • PTA1004 成绩排名(C++)
    一、问题描述:读入 n(>0)名学生的姓名、学号、成绩,分别输出成绩最高和成绩最低学生的姓名和学号。输入格式:每个测试输入包含1个测试用例,格式为第1行:正整数n第2行:第1个学生的姓名学号成绩第3行:第2个学生的姓名学号成绩.........第n+1行:第n个学生的......
  • c++打卡第十五天
    一、问题描述 二、设计思路。①、我们在此使用结构体定义结构体数组,结构体数组中包括每个阶段的征税始末,以及相对应的税率。当我们将工资传入时,会出现相应阶段的部分,以及总共应需缴纳金额。②、我们设计计算函数,通过for循环进行计算各个阶段的计算,同时使用选择语句,判断工资是......
  • C++每日打卡
    计算年龄问题定义一个Birthday类,其成员变量有3个整形变量(出生的年月日):year,month,day;提供构造方法对这3个成员变量进行初始化;成员函数有getAge(),其功能是实现计算到2017年12月25日时该Birthday对象的年龄。 #include<iostream>usingnamespacestd;classBirthday{int......
  • C++基础3: 引用
    前言本篇首先回顾指针的概念,用C指针的缺陷引出C++中的引用,然后对引用进行说明比如,什么是引用?引用解决指针什么问题?引用的特性和使用等等1.指针什么是指针指针是内存单元的地址,口语中的指针实际上是指针变量,存储地址的变量#include<stdio.h>intmain(){ i......
  • C++中什么是多态,多态需要满足什么条件,怎么使用,它的实现原理是什么?
    概念:多态是指一个接口,根据传入的参数不同,呈现多种多态,多态分为静态多态和动态多态。静态多态:像函数重载和运算符重载属于静态多态,复用函数名。它的函数地址在编译阶段就已经确定了。动态多态:通过派生类和虚函数实现运行时多态(有子类继承,子类重写父类虚函数),它的函数......
  • C++深拷贝与浅拷贝
    浅拷贝的问题默认提供的拷贝构造就是浅拷贝,如果拷贝的对象中含有成员指针变量指向堆区中的内存空间,那么就会出现两个对象中的成员指针变量指向同一块堆区空间,当方法执行结束后,对象就会被释放,调用析构函数(析构函数中存在释放在堆区开辟的内存空间),就会存在一块内存空间被多次释放......
  • c++遍历搜索关键字
    #include<iostream>#include<windows.h>#include<string.h>#include<strsafe.h>#defineMAX_INPUT_LENGTH255usingnamespacestd;voidprintMemory(char*location,longsize){ printf("\n\n---------------------location......
  • 我总结的一些 C++ 高频面试题(收藏)
    extern“C”extern是C/C++语言中表明函数和全局变量作用范围的关键字,该关键字告诉编译器,其声明的函数和变量可以在本模块或其它模块中使用。被extern"C"修饰的变量和函数是按照C语言方式编译和连接的。extern“C”这个声明的真实目的:解决名字匹配问题,实现C++与C的混合......
  • c++11 std::forward使用场景以及作用
    不使用 std::forward时,下述代码G不管传入什么类型的参数,只会最终调用 voidF(int&a);usingnamespacestd; voidF(int&a){  cout<<"int&version"<<a<<endl;} voidF(int&&a){  //dosomething  cout<<"in......