C++ WIN网络编程1

一、网络编程的基本概念

1、socket概念

        英文是插座的意思,是网络数据传输用的软件设备,创建一个socket相当于安装了一部电话机。

2、C/S概念 

  • 客户机/服务器模式在操作过程中采用主动请求的方式。
  • 服务器端:
    • 首先服务器先启动,并根据请求提供相应的服务
    • 打开一个通信通道,在某一地址和端口上接受请求。
    • 等待客户请求到达端口
    • 接受重复服务请求,处理该请求并发送应答信号
    • 返回第二步,等待另一客户请求
    • 关闭服务器
  • 客户端
    • 打开一个通信通道,并连接到服务器所在主机的特定端口
    • 向服务器发服务请求,等待并接收应答;继续提出请求。
    • 请求结束后关闭通道并终止。

3、面向连接与面向消息(TCP、UDP)

面向连接:

相当于A与B之间有了一个传送带(网络)

特点:

  • 传输过程中数据不会丢失(可靠)
  • 顺序传输数据
  • 不存在数据边界

面向消息:

特点:

  • 传输的数据可能丢失可能销毁
  • 强调快速传输而非顺序
  • 限制传输数据大小
  • 传输的数据有数据边界

二、网络编程

1、套接字类型与协议设置

  • SOCK_STREAM[流套接字]

        面向连接可靠的传输数据   是和传输大量的数据,不支持广播多播

  • SOCK_DGRAM[数据报套接字]

        无连接 广播  多播

  • SOCK_RAW[原始套接字]

        避开TCP/IP处理机制,可以直接传送给需要他的应用

引用头文件

#include<winsock2.h>

导入ws2_32.lib库

windows下的socket编程都要首先进行Winsock的初始化

2、网络编程基本函数和基本数据结构

函数名称功能描述适用范围
socket创建套接字面向连接+面向无连接的传输
bind套接字与本地IP地址和端口号的绑定面向连接+面向无连接的传输
connect请求连接面向连接的传输的客户机进程
listen侦听连接请求面向连接的传输的服务器进程
accept接受连接请求面向连接的传输的服务器进程
send往已建立连接的套接字上发送数据面向连接的传输
recv往已建立连接的套接字上接收数据面向连接的传输
sendto在无连接的套接字上发送数据主要用以无连接的传输
recvfrom在无连接的套接字上接收数据主要用以无连接的传输
close关闭套接字面向连接+面向无连接的传输

数据结构:

操作系统用

typedef struct sockaddr {

#if (_WIN32_WINNT < 0x0600)
    u_short sa_family;
#else
    ADDRESS_FAMILY sa_family;           // Address family.  16位地址类型
#endif //(_WIN32_WINNT < 0x0600)

    CHAR sa_data[14];                   // Up to 14 bytes of direct address.
}

程序员用

typedef struct sockaddr_in {

#if(_WIN32_WINNT < 0x0600)
    short   sin_family;   //16位地址类型
#else //(_WIN32_WINNT < 0x0600)
    ADDRESS_FAMILY sin_family;   
#endif //(_WIN32_WINNT < 0x0600)

    USHORT sin_port;     //16位端口号
    IN_ADDR sin_addr;    //32位IP
    CHAR sin_zero[8];    //8字节填充
}

三、手写简单服务器

TCP流程:

服务器端代码:

#include<winsock2.h>
#include<stdio.h>
#include<stdlib.h>

#pragma comment(lib,"ws2_32.lib")
int main()
{

	printf("TCP Sever\n");

	//初始化网络库
	WORD wVersionRequested;
	WSADATA wsaData;
	int err;
	wVersionRequested = MAKEWORD(2,2);
	err = WSAStartup(wVersionRequested, &wsaData);
	if (err != 0)
	{
		printf("WSAStartup errorNum = %d\n",GetLastError());
		return err;
	}

	
	if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2)
	{
		printf("LOBYTE errorNum = %d\n",GetLastError());
		WSACleanup();
		return -1;
	}


	//1 安装电话机  选中函数按F1
	SOCKET sockSrv = socket(AF_INET, SOCK_STREAM, 0);  //第三个参数由前两个决定 默认0就行
	
	
	//2 分配电话号码
	SOCKADDR_IN addrSrv;
	addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
	addrSrv.sin_family = AF_INET;
	addrSrv.sin_port = htons(6000);

	//
	if (SOCKET_ERROR == bind(sockSrv, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR)))
	{
		printf("bind errorno = %d\n", GetLastError());
		return -1;
	}
	
	//3 监听
	if (SOCKET_ERROR == listen(sockSrv, 5))
	{
		printf("listen errorno = %d\n", GetLastError());
		return -1;
	}
	printf("开始延迟");
	Sleep(20000);
	printf("结束延迟");

	SOCKADDR_IN addrCli;
	int len = sizeof(SOCKADDR);
	while (true)
	{
		//4 分配一台分ji处理客户端连接   拿起电话机准备接听	
		printf("begin accept\n");
		SOCKET sockConn = accept(sockSrv, (SOCKADDR*)&addrCli,&len);
		printf("end accept\n");

		char sendBuf[100] = { 0 };
		sprintf_s(sendBuf, 100, "Welcome to China!");
		//5 开始童话 fa收数据
		int iLen = send(sockConn,sendBuf,strlen(sendBuf),0);

		char recvBuf[100] = { 0 };
		iLen = recv(sockConn, recvBuf, 100, 0);
		printf("recvBuf = %s\n", recvBuf);

		//6 关闭分机
		closesocket(sockConn);
	}
	// 关闭总机
	closesocket(sockSrv);
   	system("pause");
	return 0;
}

  

客户端代码:

#include<winsock2.h>
#include<stdio.h>
#include<stdlib.h>

#pragma comment(lib,"ws2_32.lib")
int main()
{

	printf("TCP Client\n");

	//初始化网络库
	WORD wVersionRequested;
	WSADATA wsaData;
	int err;
	wVersionRequested = MAKEWORD(2, 2);
	err = WSAStartup(wVersionRequested, &wsaData);
	if (err != 0)
	{
		printf("WSAStartup errorNum = %d\n", GetLastError());
		return err;
	}


	if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2)
	{
		printf("LOBYTE errorNum = %d\n", GetLastError());
		WSACleanup();
		return -1;
	}


	//1 安装电话机  选中函数按F1
	SOCKET sockCli = socket(AF_INET, SOCK_STREAM, 0);  //第三个参数由前两个决定 默认0就行
	if (INVALID_SOCKET == sockCli)
	{
		printf("socket errorno = %d\n", GetLastError());
		return -1;
	}
	//2 配置要链接的服务器
	SOCKADDR_IN addrSrv;
	addrSrv.sin_addr.S_un.S_addr = inet_addr("192.168.1.7");
	addrSrv.sin_family = AF_INET;
	addrSrv.sin_port = htons(6000);

	//3 连接服务器
	
	if (SOCKET_ERROR == connect(sockCli, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR)))
	{
		printf("bind errorno = %d\n", GetLastError());
		system("pause");
		return -1;
	}

	//4 收发数据
	char recvBuf[100] = { 0 };
	int iLen = recv(sockCli, recvBuf, 100, 0);
	printf("recvBuf = %s\n", recvBuf);

	const char sendBuf[100] =  "zsywan";
	iLen = send(sockCli, (char*)sendBuf, 100, 0);

	//5 关闭总ji
	closesocket(sockCli); 
	WSACleanup();
	system("pause");
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值