网络编程 开篇

视频解析:【C/C++网络编程】多客户端聊天室!多线程+网络编程实现多人聊天功能,可以实现多客户端的简单通讯 ~_哔哩哔哩_bilibili

网络视频:socket到底是什么?_哔哩哔哩_bilibili

目录

客户端

服务器端进行网络通信的流程

 1.确定协议版本

 2.创建Socket

3.确定服务器协议地址簇 

 4.绑定

 5.监听

 6.接受客户端连接

7.通信

 8.关闭socket

9.清理协议

 客户端进行网络通信的流程

    4.连接服务器

5.通信

6.关闭socket

7.清理协议

代码整理 

客户端

服务器端


客户端

服务器端进行网络通信的流程

1.确定协议版本

 2.创建Socket

3.确定服务器协议地址簇

4.绑定

5.监听

6.接收客户端链接

7.通信

8.关闭socket

 1.确定协议版本

先声明一个WSAData类型的变量

WSAData wsadata;

然后输入:"WSAStartup",选中它,按F1会转到帮助文档. 文档里说明了要使用WSAStartup的要求:

 通过MAKEWORD这个宏指定主版本为2,副版本为2的协议:

然后加上判断

WSAStartup(MAKEWORD(2, 2), &wsadata);
if (LOBYTE(wsadata.wVersion) != 2 ||
		HIBYTE(wsadata.wVersion) != 2)
	{
		printf("确定网络协议版本失败!\n");
		system("pause");
		return -1;
	}
	else printf("确定网络协议版本成功!\n");

 2.创建Socket

这一步照抄

	SOCKET socketserver = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
	if (SOCKET_ERROR == socketserver)
	{
		printf("创建socket失败,%d\n",GetLastError());
		WSACleanup();  //如果失败就把协议清理掉
		system("pause");
		return -1;
	}
	else printf("创建socket成功!\n");

3.确定服务器协议地址簇 

 SOCKADDR_IN就是一个结构体,里面有IP地址,端口号这些成员变量.一个IP地址确定一台主机,端口号确定APP;

    SOCKADDR_IN addr = { 0 };                           
	addr.sin_family = AF_INET;                           //照抄上面的
	addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");  //ip地址
	addr.sin_port = htons(9527);                         //端口号

 4.绑定


	int r = bind(socketserver,(sockaddr*)&addr,sizeof addr);
	if (-1== r)
	{
		printf("绑定失败,%d\n", GetLastError());
		WSACleanup();  //如果失败就把协议清理掉
		system("pause");
		return -1;
	}
	else printf("绑定成功!\n");

 5.监听

	r = listen(socketserver,10);
	if (-1 == r)
	{
		printf("监听失败,%d\n", GetLastError());
		WSACleanup();  //如果失败就把协议清理掉
		system("pause");
		return -1;
	}
	else printf("监听成功!\n");

 6.接受客户端连接


		SOCKET clientSocket = accept(socketserver, (sockaddr*)NULL, NULL);  //后两个参数是客户端的ip,端口号
		if (-1 == clientSocket)
		{
			printf("服务器崩溃,%d\n", GetLastError());
			WSACleanup();  //如果失败就把协议清理掉
			system("pause");
			return -1;
		}
		else printf("有客户端链接服务器\n");
		CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)tongxun, (LPVOID)i, NULL, NULL);
	

7.通信

	char buff[56];  //接收客户端发来的信息
	while (1)
	{
		r = recv(clientSocket, buff, 55, NULL); //最多接收55条,因为还要留一个给结束符
		if (r > 0)                         //如果接收到消息了就添加一个结束符
		{
			buff[r] = 0;
			printf(">>%s\n", buff);
		}
	}

 8.关闭socket

   closesocket(socketserver);

9.清理协议

   WSACleanup();	

 客户端进行网络通信的流程

1.确定协议版本

 2.创建Socket

3.确定服务器协议地址簇

4.连接服务器

5.通信

6.关闭socket

7.清理协议

1,2,3步骤和服务器端一样,第四个步骤如下:

    4.连接服务器

    int r = connect(socketserver, (sockaddr*)&addr, sizeof addr);
	if (-1 == r)
	{
		printf("连接服务器失败!\n");
		WSACleanup();  //如果失败就把协议清理掉
		system("pause");
	}
	else printf("连接服务器成功!\n");

5.通信

	//循环接收用户输入,发送给服务器
	char buff[56];
	while (1)
	{
			scanf("%s", buff);
			send(socketserver, buff, strlen(buff), NULL);
	
	}

6.关闭socket

closesocket(socketserver);

7.清理协议

WSACleanup();


此时,只能做到客户端与服务器端一对一通信:

我们现在想实现多个客户端与服务器端进行通信,就要用到io多路复用,多线程等技术.我们这里用多线程.

我们在接收客户端连接这一部分进行修改:

我们将上文定义的SOCKET clientSocket变为SOCKET clientSocket[].这样就可以接受多条客户端的链接.我们设置一个for循环,在循环中通过下标自增来接受多个客户端链接的请求,代码如下:

for (int i = 0; i < NUM; i++)  //可以接受NUM个客户端的链接
 	{
		clientSocket[i] = accept(socketserver, (sockaddr*)NULL, NULL);  //后两个参数是客户端的ip,端口号
		if (-1 == clientSocket[i])
		{
			printf("服务器崩溃,%d\n", GetLastError());
			WSACleanup();  //如果失败就把协议清理掉
			system("pause");
			return -1;
		}
		else printf("有客户端链接服务器\n");
		CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)tongxun, (LPVOID)i, NULL, NULL);
	}

这样我们就可以多个客户端与服务器端进行通信了:

代码整理 

客户端

#define _CRT_SECURE_NO_WARNINGS 1
#define _WINSOCK_DEPRECATED_NO_WARNINGS  //为了消除警告

#include<stdio.h>

#include <winsock2.h>
#include<windows.h>
#pragma comment(lib, "ws2_32.lib")

int main()
{

	//第一步确定协议版本
	WSAData wsadata;
	WSAStartup(MAKEWORD(2, 2), &wsadata);
	if (LOBYTE(wsadata.wVersion) != 2 ||
		HIBYTE(wsadata.wVersion) != 2)
	{
		printf("确定网络协议版本失败!\n");
		system("pause");
		return -1;
	}
	else printf("确定网络协议版本成功!\n");


	//第二步创建Socket
	SOCKET socketserver = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if (SOCKET_ERROR == socketserver)
	{
		printf("创建socket失败,%d\n", GetLastError());
		WSACleanup();  //如果失败就把协议清理掉
		system("pause");
		return -1;
	}
	else printf("创建socket成功!\n");

	//3.确定服务器协议地址簇
	SOCKADDR_IN addr = { 0 };                            //SOCKADDR_IN就是一个结构体
	addr.sin_family = AF_INET;                           //照抄上面的
	addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");  //ip地址
	addr.sin_port = htons(9527);                         //端口号

	//4.连接服务器
	int r = connect(socketserver, (sockaddr*)&addr, sizeof addr);
	if (-1 == r)
	{
		printf("连接服务器失败!\n");
		WSACleanup();  //如果失败就把协议清理掉
		system("pause");
	}
	else printf("连接服务器成功!\n");




	//5.通信
	//循环接收用户输入,发送给服务器
	char buff[56];
	while (1)
	{
			scanf("%s", buff);
			send(socketserver, buff, strlen(buff), NULL);
	
	}


	//6.关闭socket
	closesocket(socketserver);

	//7.清理协议
	WSACleanup();

	return 0;
}

服务器端

#define _CRT_SECURE_NO_WARNINGS 1
#define _WINSOCK_DEPRECATED_NO_WARNINGS  //为了消除警告

#include<stdio.h>

#include <winsock2.h>
#include<windows.h>
#pragma comment(lib, "ws2_32.lib")

#define NUM 1024
SOCKET clientSocket[1024];


void tongxun(int idx);
int main()
{

	//第一步确定协议版本
	WSAData wsadata;
	WSAStartup(MAKEWORD(2, 2), &wsadata);
	if (LOBYTE(wsadata.wVersion) != 2 ||
		HIBYTE(wsadata.wVersion) != 2)
	{
		printf("确定网络协议版本失败!\n");
		system("pause");
		return -1;
	}
	else printf("确定网络协议版本成功!\n");
    

	//第二步创建Socket
	SOCKET socketserver = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
	if (SOCKET_ERROR == socketserver)
	{
		printf("创建socket失败,%d\n",GetLastError());
		WSACleanup();  //如果失败就把协议清理掉
		system("pause");
		return -1;
	}
	else printf("创建socket成功!\n");

	//3.确定服务器协议地址簇
	SOCKADDR_IN addr = { 0 };                            //SOCKADDR_IN就是一个结构体
	addr.sin_family = AF_INET;                           //照抄上面的
	addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");  //ip地址
	addr.sin_port = htons(9527);                         //端口号

	//4.绑定
	int r = bind(socketserver,(sockaddr*)&addr,sizeof addr);
	if (-1== r)
	{
		printf("绑定失败,%d\n", GetLastError());
		WSACleanup();  //如果失败就把协议清理掉
		system("pause");
		return -1;
	}
	else printf("绑定成功!\n");

	//5.监听
	r = listen(socketserver,10);
	if (-1 == r)
	{
		printf("监听失败,%d\n", GetLastError());
		WSACleanup();  //如果失败就把协议清理掉
		system("pause");
		return -1;
	}
	else printf("监听成功!\n");
	

	//6.接收客户端链接
	for (int i = 0; i < NUM; i++)  //可以接受NUM个客户端的链接
 	{
		clientSocket[i] = accept(socketserver, (sockaddr*)NULL, NULL);  //后两个参数是客户端的ip,端口号
		if (-1 == clientSocket[i])
		{
			printf("服务器崩溃,%d\n", GetLastError());
			WSACleanup();  //如果失败就把协议清理掉
			system("pause");
			return -1;
		}
		else printf("有客户端链接服务器\n");
		CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)tongxun, (LPVOID)i, NULL, NULL);
	}
	

	//8.关闭socket
	closesocket(socketserver);
	
	//9.清理协议
	WSACleanup();	



	return 0;
}
void tongxun(int idx)
{
	int r;
	//7.通信
	char buff[56];  //接收客户端发来的信息
	while (1)
	{
		r = recv(clientSocket[idx], buff, 55, NULL); //最多接收55条,因为还要留一个给结束符
		if (r > 0)                         //如果接收到消息了就添加一个结束符
		{
			buff[r] = 0;
			printf(">>%s\n", buff);
		}
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

孙鹏宇.

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

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

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

打赏作者

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

抵扣说明:

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

余额充值