socket聊天室代码

Server:

#include
#include"winsock2.h"
#include"WS2tcpip.h"  //本程序用到地址转换函数inet_pton(),所以要包含该头文件
#include"process.h"
#include
#include
#include
//#include
#define PORT 65432    //定义要访问的服务器端口常量
#define MSG_SHOW 1
#define MSG_CREATE 2
#define MSG_JOIN 3
#define MSG_LEAVE 4
#define MSG_QUIT 5
#define MSG_EXIT 5
#define MSG_TALK 6
#pragma comment(lib,"ws2_32.lib")
using namespace std;
class MsgHead {
public:
	int msgType;
	int	dataLength;
};
class MsgShow :public MsgHead
{
public:
	MsgShow() {
		msgType = MSG_SHOW;
		dataLength = sizeof(MsgShow);
	}

};
class MsgCreate :public MsgHead
{
public:
	MsgCreate() {
		msgType = MSG_SHOW;
		dataLength = sizeof(MsgCreate);
	}

};
class MsgJoin :public MsgHead
{
public:
	MsgJoin() {
		msgType = MSG_SHOW;
		dataLength = sizeof(MsgJoin);
	}

};
class MsgLeave :public MsgHead
{
public:
	MsgLeave() {
		msgType = MSG_SHOW;
		dataLength = sizeof(MsgLeave);
	}

};
class MsgExit :public MsgHead
{
public:
	MsgExit() {
		msgType = MSG_SHOW;
		dataLength = sizeof(MsgExit);
	}

};
class MsgTalk :public MsgHead
{
	char buff[1024];
public:
	MsgTalk() {
		memset(buff, '\0', sizeof(buff));
		msgType = MSG_TALK;
		dataLength = sizeof(MsgTalk);
	}
	char* getBuff() {
		return buff;
	}
};
void dealWithData(MsgHead* msg,SOCKET sClient) {

	if (msg->msgType == MSG_SHOW) {
		cout << "显示聊天室" << endl;
	}
	else if (msg->msgType == MSG_CREATE){
		cout << "创建聊天室" << endl;
	}
	else if (msg->msgType ==  MSG_JOIN) {
		cout << "加入聊天室" << endl;
	}
	else if (msg->msgType == MSG_LEAVE) {
		cout << "离开聊天室" << endl;
	}
	else if ((msg->msgType == MSG_QUIT ) || (msg->msgType ==  MSG_EXIT)) {
		cout << "退出" << endl;
	}
	else if (msg->msgType == MSG_TALK) {
		cout << "开始聊天" << endl;
		//MsgTalk* msgtalk = (MsgTalk*)buff;
		cout << ((MsgTalk*)msg)->getBuff() << endl;
		
	}
}

int main()
{
	SOCKET sock_server, newsock;
	struct sockaddr_in addr, client_addr;
	unsigned hThread;


	/*初始化winsock DLL*/
	WSADATA wsaData;
	if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
	{
		cout << "加载winsock.dll失败!\n";
		return 0;
	}

	/*创建套接字*/
//	if ((sock_server=socket(AF_INET,SOCK_STREAM,0))==INVALID_SOCKET)

	if ((sock_server = socket(AF_INET, SOCK_STREAM, 0)) == SOCKET_ERROR)
	{
		cout << "创建套接字失败!" << WSAGetLastError() << endl;
		WSACleanup();
		return 0;
	}

	/*绑定IP端口*/
	int addr_len = sizeof(struct sockaddr_in);
	memset((void*)&addr, 0, addr_len);
	addr.sin_family = AF_INET;
	addr.sin_port = htons(PORT);
	addr.sin_addr.s_addr = htonl(INADDR_ANY);

	/*给监听套接字绑定地址*/
//	if (bind(sock_server,(LPSOCKADDR)&addr,sizeof(addr))!=0)
	if (bind(sock_server, (const sockaddr *)&addr, sizeof(addr)) != 0)
	{
		cout << "绑定地址失败!" << WSAGetLastError() << endl;
		closesocket(sock_server);
		WSACleanup();
		return 0;
	}

	/*开始监听*/
	if (listen(sock_server, 0) != 0)
	{
		cout << "listen函数调用失败!" << WSAGetLastError() << endl;
		closesocket(sock_server);
		WSACleanup();
		return 0;
	}
	else
	{
		cout << "listenning......\n";
	}
	/*接收并处理客户连接*/
	FD_SET fd_read; //fd_set 里面放的是socket,是一个socket集合
	FD_ZERO(&fd_read);
	FD_SET(sock_server, &fd_read);
	FD_SET copy(fd_read);
	while (true) {
		const timeval tv = { 1,0 }; 
		fd_read = copy;
		//cout << fd_read.fd_count << endl;
		int ret = select(NULL, &fd_read, NULL, NULL, &tv);//select会识别有没有网络事件发送,若没有就阻塞在这里。加了个timeval代表让他等一秒就往下执行
		/*cout << fd_read.fd_count << endl;
		cout << fd_read.fd_array[0] << endl;
		cout << fd_read.fd_array[1] << endl;*/
		int fdCount = fd_read.fd_count;
		for (int i = 0;i < fdCount;i++) {
			if (fd_read.fd_array[i] == sock_server) {
				cout << 1 << endl;
				sockaddr_in clientAddr;
				int nlen = sizeof(sockaddr_in);
				SOCKET sClient = accept(sock_server, (sockaddr*)&clientAddr, &nlen);
				 /* 第一个参数sockfd为服务器的socket描述字,
					第二个参数addr为指向struct sockaddr* 的指针,用于返回客户端的协议地址,
					第三个参数addrlen为协议地址的长度。*/
				if (sClient == SOCKET_ERROR) {
					cout << "接收客户端失败" << endl;
					closesocket(sock_server);
					return -1;
				}
				else cout << "连接客户端成功" << endl;
				FD_SET(sClient, &fd_read);
				FD_SET(sClient, &copy);
			}
			else {
				char msg[1024];
				memset(msg, '\0', sizeof(msg));
				
				int res = recv(fd_read.fd_array[i], msg, 20, 0);
				dealWithData((MsgHead *) msg,fd_read.fd_array[i]);
				if (res <= 0) {
					FD_CLR(fd_read.fd_array[i], &copy);
					cout << "用户退出" << endl;
					break;
				}
			}
		}
	} 


	closesocket(newsock);
	closesocket(sock_server);
	WSACleanup();
	return 0;
}

void tcpsend(void* par)
{

	int size;
	SOCKET sock = (SOCKET)par;
	while (true)
	{
		char msg[1000];
		memset(msg, '\0', sizeof(msg));
		if ((size = recv(sock, msg,99, 0)) < 0)
		{
			cout << "接收信息失败,错误码:" << WSAGetLastError() << endl;
			break;
		}
		else if (size == 0)
		{

			break;
		}
		else   //输出收到的数据
		{
			//将数据中的整型数据字段的值由网络字节顺序转换为主机字节顺序
			//stud.examination = htonl(stud.examination);
			cout << "收到的消息:" << msg << endl;;
		

		}
	}
}




Client:

#include 
#include 
#include 
#include 
#include  
#include
#include
#include
#include
#include
#define PORT 65432
#define MSG_SHOW 1
#define MSG_CREATE 2
#define MSG_JOIN 3
#define MSG_LEAVE 4
#define MSG_QUIT 5
#define MSG_EXIT 5
#define MSG_TALK 6
#pragma comment(lib, "Ws2_32.lib")
using namespace std;
class MsgHead {
public:
	int msgType;
	int	dataLength;
};
class MsgShow:public MsgHead
{
public:
	MsgShow() {
		msgType = MSG_SHOW;
		dataLength = sizeof(MsgShow);
	}

};
class MsgCreate :public MsgHead
{
public:
	MsgCreate() {
		msgType = MSG_SHOW;
		dataLength = sizeof(MsgCreate);
	}

};
class MsgJoin :public MsgHead
{
public:
	MsgJoin() {
		msgType = MSG_SHOW;
		dataLength = sizeof(MsgJoin);
	}

};
class MsgLeave :public MsgHead
{
public:
	MsgLeave() {
		msgType = MSG_SHOW;
		dataLength = sizeof(MsgLeave);
	}

};
class MsgExit :public MsgHead
{
public:
	MsgExit() {
		msgType = MSG_SHOW;
		dataLength = sizeof(MsgExit);
	}

};
class MsgTalk :public MsgHead
{
	char buff[1024];
public:
	MsgTalk() {
		memset(buff, '\0', sizeof(buff));
		msgType = MSG_TALK;
		dataLength = sizeof(MsgTalk);
	}
	char* getBuff() {
		return buff;
	}
};
LPVOID chat(LPVOID ptr) {
	SOCKET sClient = *(SOCKET*)ptr;
	cout << "please input: show create join leave exit/quit" << endl;
	while (1) {
		char buff[1024];
		gets_s(buff);  //会清掉最后输的换行符
		if (strcmp(buff, "show") == 0) {
			//显示聊天室
		}
		else if (strcmp(buff, "join") == 0) {
			//加入一个聊天室
		}
		else if (strcmp(buff, "create") == 0) {
			//创建一个聊天室
		}
		else if (strcmp(buff, "talk") == 0) {
			cout << "开始聊天" << endl;
			MsgTalk msgTalk;
			while (1) {
				gets_s(msgTalk.getBuff(), 1000);
				send(sClient, (const char*)&msgTalk, msgTalk.dataLength, 0);
			}
		}
	 }
}

int main() {

	
	/*定义相关变量*/
	int sock_client;							//定义客户端套接字
	struct sockaddr_in server_addr;				//定义存放服务器端地址的结构变量
	int addr_len = sizeof(struct sockaddr_in);	//地址结构变量长度
	/*初始化*/
	WSADATA wsaData;
	if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
	{
		cout << "加载winsock.dll失败!\n";
		return 0;
	}
	/*创建套接字*/
	if ((sock_client = socket(AF_INET, SOCK_STREAM, 0)) < 0)
	{
		cout << "创建套接字失败!错误代码:" << WSAGetLastError() << endl;
		WSACleanup();
		return 0;
	}
	/*输入服务器IP地址以及填写服务器地址结构*/
	char IP[20];
	cout << "请输入服务器地址:";
	cin >> IP;
	memset((void*)&server_addr, 0, addr_len);//地址结构清零
	server_addr.sin_family = AF_INET;
	server_addr.sin_port = htons(PORT);
	in_addr a;
	inet_pton(AF_INET, IP, &a);
	server_addr.sin_addr.s_addr = a.S_un.S_addr;//服务器IP地址
	/*Connecting Server*/
	SOCKET_ERROR;
	if (connect(sock_client, (struct sockaddr*)&server_addr, addr_len) != 0)
	{
		cout << "Connecting Error!!" << WSAGetLastError() << endl;
		closesocket(sock_client);
		WSACleanup();
		return 0;
	}
	chat(&sock_client);
	//future futureResult = async(chat,&sock_client);
	
	while (1) {
		char buff[1000];
		
		int ret = recv(sock_client, buff, 1024, 0);
		if (ret > 0) {

		}
		else {
			cout << "客户端接收数据失败" << endl;
		}
		
	}
	//HANDLE = futureResult.get();
	//WaitForSingleObject();
	closesocket(sock_client);
	WSACleanup();

	return 0;
}

你可能感兴趣的:(网络,socket)