c++:利用socket基于TPC/IP实现通信 在线聊天

1.前言

希望大家合着参考资料一起看,对初入网络编程的童鞋更加友好。

2.效果展示

客户端:
在这里插入图片描述
服务器端:
在这里插入图片描述

2.socket(套接字)介绍

SOCKET中文翻译过来就是套接字的意思。
套接字是通信的基石,是支持TCP/IP协议的路通信的基本操作单元。可以将套接字看作不同主机间的进程进行双间通信的端点,它构成了单个主机内及整个网络间的编程界面。套接字存在于通信域中,通信域是为了处理一般的线程通过套接字通信而引进的一种抽象概念。(来自百度百科)
在这里插入图片描述
对套接字这个概念有点迷糊?没有关系,我们最重要的是知道如何使用它,要通过TCP/IP再网络中进行通信,对方的IP地址和端口号肯定是要知道的吧,我们只需要将IP地址和端口号写入套接字中,再通过操控套接字,向套接字中灌入信息,或者从套接字中取出信息,就可以实现向已知的IP地址和端口号所指向的应用程序进行通信了。
简而言之,套接字就是系统提供给应用程序用来进行网络操作的接口。

3.代码实现

服务器端代码:

//此代码在vs2020中实测能编译成功
//在devc++中编译需要在 项目->属性->参数->连接器->加入库或者对象 中选择libws2_32.a库并添加
//操控socket需要使用winsock.h库
#include <winsock.h>
#include <iostream>
//添加编译命令
#pragma comment(lib,"ws2_32.lib")
using namespace std;
//initwsa函数用来初始化socket,WSA是windows socket api 的简写
int initwsa();
int main() {
	/*在此程序中,我们需要定义两个套接字,在网络中每时每刻有太多消息,我们首先需要用第一个套接字
	s_server来监听,当到来的消息指定的IP地址和端口号都对的上的时候,就将其放行,并放入缓冲区,如
	果缓冲中没有其他消息,就将与第二个套接字s_accept与其进行连接并进行通信,通信完成后再与缓冲区
	的下一个进行连接。
	*/
	SOCKET s_accept;
	SOCKET s_server;
	SOCKADDR_IN server_addr;
	SOCKADDR_IN accept_addr;
	if (!initwsa())return 0;
	server_addr.sin_family = AF_INET;
	server_addr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);//INADDR_ANY是本机所有网卡所有IP地址的意思
	server_addr.sin_port = htons(5010);
	s_server = socket(AF_INET, SOCK_STREAM, 0);
	//绑定套接字
	if (bind(s_server, (SOCKADDR*)&server_addr, sizeof(server_addr)) == SOCKET_ERROR) {
		cout << "套接字绑定失败!!" << endl;
		WSACleanup();
		return 0;

	}
	else {
		cout << "套接字绑定成功!!" << endl;
	}
	//设置监听
	if (listen(s_server, SOMAXCONN) < 0) {
		cout << "设置监听失败!!" << endl;
		WSACleanup();
		return 0;
	}
	else {
		cout << "设置监听成功!!" << endl;
	}
	cout << "服务端正在监听连接,请稍后......" << endl;
	//连接
	int len = sizeof(SOCKADDR);
	s_accept = accept(s_server, (SOCKADDR*)&accept_addr, &len);
	if (s_accept == SOCKET_ERROR) {
		cout << "连接失败!!" << endl;
		WSACleanup();
		return 0;
	}
	cout << "连接建立,准备接受数据!!" << endl;
	char recv_buf[100];
	char send_buf[100];
	int recv_len = 0;
	int send_len = 0;
	while (1) {
		//收发消息
		recv_len = recv(s_accept, recv_buf, 100, 0);
		if (recv_len < 0) {
			cout << "接受失败!!" << endl;
		}
		else {
			cout << "客户端消息:" << recv_buf << endl;
		}
		cout << "请输入回复消息:";
		cin >> send_buf;
		send_len = send(s_accept, send_buf, 100, 0);
		if (send_len < 0) {
			cout << "发送消息失败!!" << endl;
			break;
		}
	}
	closesocket(s_server);
	closesocket(s_accept);
	WSACleanup();
	return 0;

}
int initwsa() {
	WSADATA wsaDATA;
	if (!WSAStartup(MAKEWORD(2, 2), &wsaDATA)) {
		cout << "初始化套接字字库成功!!" << endl;
		return 1;
	}
	else {
		cout << "初始化套接字字库失败!!" << endl;
		return 0;
	}
}

客户端代码

//编译要求同服务器端代码相同
#include <winsock.h>
#include <iostream>
#pragma comment(lib,"ws2_32.lib")
using namespace std;
int initwsa();
int main() {
	SOCKET s_server;
	SOCKADDR_IN server_addr;
	cout << "请输入要连接的IP地址:" << endl
	char ipadd[50];
	cin >> ipadd;
	if (!initwsa())return 0;
	server_addr.sin_family = AF_INET;
	server_addr.sin_addr.S_un.S_addr = inet_addr(ipadd);
	server_addr.sin_port = htons(5010);
	s_server = socket(AF_INET, SOCK_STREAM, 0);
	//发起连接
	if (connect(s_server, (SOCKADDR*)&server_addr, sizeof(SOCKADDR)) == SOCKET_ERROR) {
		cout << "服务器连接失败!!" << endl;
		WSACleanup();
		return 0;
	}
	else {
		cout << "服务器连接成功!!" << endl;
	}
	char recv_buf[100];
	char send_buf[100];
	int recv_len = 0;
	int send_len = 0;
	while (1) {
		//收发消息
		cout << "请输入回复消息:";
		cin >> send_buf;
		send_len = send(s_server, send_buf, 100, 0);
		if (send_len < 0) {
			cout << "发送消息失败!!" << endl;
			break;
		}
		recv_len = recv(s_server, recv_buf, 100, 0);
		if (recv_len < 0) {
			cout << "接受失败!!" << endl;
		}
		else {
			cout << "服务端消息:" <<recv_buf<< endl;
		}
		
	}
	closesocket(s_server);
	WSACleanup();
	return 0;
	
}
int initwsa() {
	WSADATA wsaDATA;
	if (!WSAStartup(MAKEWORD(2, 2), &wsaDATA)) {
		cout << "初始化套接字字库成功!!" << endl;
		return 1;
	}
	else {
		cout << "初始化套接字字库失败!!" << endl;
		return 0;
	}
}

4.参考

socket库参考资料:socket编程c++
原代码链接:原代码

5.拓展与延伸

给大家出几个可以拓展的点子:
1.与文件打包程序绑定在一起实现将文件上传到服务器
2.加入数据库实现多客户端的在线聊天室
3.与小游戏绑定实现全球排行榜功能

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值