网络并发一Socket(TCP)一个简单的服务端Seriver

本文详细介绍了TCP/IP通信中客户端和服务器端的交互步骤,从创建套接字到数据的发送与接收,包括连接、监听、接受和关闭等关键操作。示例代码展示了Windows环境下使用WinSock2库实现的TCP服务端程序。
摘要由CSDN通过智能技术生成

在这里插入图片描述
一.Client客户端
客户端可以先简单看做是一个读写文件的过程
1.建立一个套接字socket(相当于打开一个文件指针File*)
2.连接服务器(打开文件fopen)
3.向服务端发送数据(向文件中写数据,fwrite)
4.接收服务数据(读取文件数据,fread)
5.关闭Socket(关闭文件fclose)

建立好客户端后我们需要通过ip地址和端口号链接到服务端的程序
ip地址时服务器的机器的地址
port端口号时在服务器上运行中的网路服务程序。
完成后可以发送和接收数据

二.服务端
1.建立一个Socket(申请一个端口好用来相应服务请求)
2.绑定端口bind(设置一个端口号)
3.监听网络端口listen(等待客服端消息)
4.等待客户端链接accept(阻塞到客户端链接)
5.接收客户端数据recv(阻塞到有数据可读)
6.向客户端返回数据send(组赛到数据发送完成)
7.关闭Socket closesocket

// 加这个宏定义也可以规避sock2和window.h的重编译问题
#define WIN32_LEAN_AND_MEAN
#define _WINSOCK_DEPRECATED_NO_WARNINGS

//winsock2一定要在windows前,否则会有宏定义重编译问题。sock2是新库,windows是老库。
#include<WinSock2.h>
#include<Windows.h>
#include<iostream>

//加入静态链接库,否则会出现问题:无法解析的外部符号 __imp__WSAStartup@8
//也可以在属性页、连接器、输入、附加依赖项中输入ws_32.lib
#pragma comment(lib,"ws2_32.lib")
int main()
{

	//版本号
	WORD ver = MAKEWORD(2, 2);
	//数据指针
	WSADATA dat;
	//windows下socket的启动函数,启动socket环境
	WSAStartup(ver, &dat);

	//开始编写网络环境
	//1.建立一个socket。套接字inet6为最新,数据类型:数据流,网络类型tcp,udp
	//定义返回类型,用来储存socket数据(uint型)
	SOCKET _sock=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);

	//2 bind 绑定用于接受客户端连接的网络端口
	//sock地址的结构体
	sockaddr_in _sin = {};
	//网络类型
	_sin.sin_family = AF_INET;
	//端口号htons(host to net unsigned short)主机到网络的字节序的转换.用来寻找服务程序
	_sin.sin_port = htons(4567);
	//定义IP地址,主机不只一个IP地址。cmd中ipconfig可以查看。
	//如果纯内网127就可以。还可以屏蔽外网的访问。
	//S_un是一个联合体。
	//INADDR_ANY不限定网路地址。
	//_sin.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
	_sin.sin_addr.S_un.S_addr = INADDR_ANY;
	//sock名,地址,地址长度。强制转换地址类型sockaddr结构体里的数据类型不利于我们直接填写,
	//addr_in的结构体与普通addr结构体相同,而且有常见的数据类型方便填写。
	if (SOCKET_ERROR==bind(_sock, (sockaddr*)&_sin, sizeof(_sin)))//判断是否绑定成功
	{
		//如果端口号被别的程序占用,就是绑定失败
		printf("ERROR,绑定用于接受客户端连接的网络端口失败\n");
	}
	else
	{
		printf("绑定网络端口成功\n");
	}

	//3.listen监听网络端口
	//最大等待5人来连接
	if (SOCKET_ERROR == listen(_sock, 5))
	{
		printf("ERROR,监听失败\n");
	}
	else
	{
		printf("监听成功\n");
	}

	//4 accept 等待客户端连接
	sockaddr_in clientAddr = {};
	//定义client返回的socket数据的长度
	int nAddrlen = sizeof(sockaddr_in);
	//定义一个无效的sock地址用来进行判断
	SOCKET _cSock = INVALID_ATOM;
	//定义发送数据,
	char msgBuf[] = "There is Server!";
	//如果固定长读就在在循环外计算出发送数据的长度,节省计算时间
	//int bufSize = sizeof(msgBuf);
	//循环重复执行
	while (true)
	{
		//返回一个客户端的socket网络地址
		_cSock = accept(_sock, (sockaddr*)&clientAddr, &nAddrlen);
		//判断
		if (INVALID_SOCKET == _cSock)
		{
			printf("错误,接收到无效客户端SOCKET\n");
		}
		else {
			//inet_ntoa 把客户端转换成可读的ip地址
			//inet_ntoa 过时了,需要定义一个宏define _WINSOCK_DEPRECATED_NO_WARNINGS
			printf("新客户端加入:IP=%s \n", inet_ntoa(clientAddr.sin_addr));
		}
		
		//5.send 向客户端发送数据
		
		//+1把字符串结尾\0参数也加入长度,把\0页发送出去,0是默认flag参数
		send(_cSock, msgBuf, strlen(msgBuf) + 1, 0);
	}
	//6. 关闭自身的套节字
	closesocket(_sock);
	//结束编写网路环境

	//结束socket
	WSACleanup();
	std::cout << "this is server" << std::endl;
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值