udp多人聊天室 1-server n-client

通过udp实现一个聊天室。

只需要1个服务器 ,可以支持n个client。

服务器的工作就是接收到消息并转发给其他客户端。客户端需要同时开启接收了发送线程,时时刻刻接收服务器发来的信息以及将自己的信息发送到服务器上。


server:

#include<WinSock2.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#pragma comment(lib,"ws2_32.lib")

#define DEFAULT_PORT 5051//FOR RECV
#define DEFAULT_PORTSEND 5052//FOR SEND
#define BUFFER_LENGTH 1000

typedef struct
{
	char ip[20];
	char name[10];
	bool in;
}CLIENT;

CLIENT clic[1000];
int ci=-1;
void main()
{
	int iPort=DEFAULT_PORT;
	WSADATA wsaData;
	SOCKET sSocket;

	int iLen;

	int iSend;

	int iRecv;

	char send_buf[1000];

	char recv_buf[BUFFER_LENGTH];

	struct sockaddr_in ser,cli;

	printf("----------------------\n");
	printf("Server Waiting\n");
	printf("----------------------\n");


	if(WSAStartup(MAKEWORD(2,2),&wsaData)!=0)
	{printf("Failed to load Winsock.\n");return;}

	sSocket=socket(AF_INET,SOCK_DGRAM,0);
	if(sSocket==INVALID_SOCKET){printf("socket()Faild:%d\n",WSAGetLastError());return;}

	ser.sin_family=AF_INET;
	ser.sin_port=htons(iPort);
	ser.sin_addr.s_addr=htonl(INADDR_ANY);

	if(bind(sSocket,(LPSOCKADDR)&ser,sizeof(ser))==SOCKET_ERROR)
	{printf("bind()Faild:%d\n",WSAGetLastError());return;}

	iLen=sizeof(cli);

	memset(recv_buf,0,sizeof(recv_buf));

	while(1)
	{
		//接收数据包 确定cli  表示 cli存有客户端发来的 ip和port 
		iRecv=recvfrom(sSocket,recv_buf,BUFFER_LENGTH,0,(SOCKADDR*)&cli,&iLen);
		if(iRecv==SOCKET_ERROR)
		{printf("recvfrom()Faild:%d\n",WSAGetLastError());return;}
		else if(iRecv==0) break;
		else 
		{// 接收到了正确数据
			printf("recv:%s\n",recv_buf);
			printf("Accepted client IP:[%s],port:[%d]\n",inet_ntoa(cli.sin_addr),ntohs(cli.sin_port));  
			//newuser  newsays

			char tempstr[1024];
			strncpy(tempstr,recv_buf,7);
			tempstr[7]='\0';
			//printf("tempstr=%s\n",tempstr);

			if(strcmp(tempstr,"newuser")==0)
			{
				printf("this is a new user\n");

				ci++;
				strcpy(clic[ci].name,recv_buf+7);
				strcpy(clic[ci].ip,inet_ntoa(cli.sin_addr));
				clic[ci].in=1;

			}
			else if(strcmp(tempstr,"newsays")==0)
			{
				printf("this is a new say\n");

				int i;
				for(i=0;i<=ci;i++)
				{
					if(clic[i].in==1 && strcmp(clic[i].ip,inet_ntoa(cli.sin_addr))==0) 
					{
						printf("找到该用户,名字为%s\n",clic[i].name);
						break;
					}
				}
				if(i>ci){printf("未从服务器中找到该用户,发生错误!\n");}

				if(strcmp("exit",recv_buf+7)==0)
				{
					clic[i].in=0;
				}
				else
				{
				strcpy(send_buf,clic[i].name);
				strcat(send_buf,":");
				strcat(send_buf,recv_buf+7);
				int t;
				for(t=0;t<=ci;t++)
				{
					if(clic[t].in==0 || t==i)continue;
					cli.sin_addr.s_addr=inet_addr(clic[t].ip);
					cli.sin_port=htons(DEFAULT_PORTSEND);
					iSend=sendto(sSocket,send_buf,sizeof(send_buf),0,(SOCKADDR*)&cli,sizeof(cli));
					printf("服务器已经向%s广播该信息:%s\n",clic[t].name,send_buf);
					if(iSend==SOCKET_ERROR)
					{
						printf("sendto()Failed.:%d\n",WSAGetLastError());
						break;
					}
					else if(iSend==0) break;
					else
					{
						printf("sendto() succeeded !\n");
						printf("----------------------\n");
					}
				}
				}
			}
			else printf("recv error!\n");
		}
	}
	closesocket(sSocket);
	WSACleanup();
}

client:

#include<WinSock2.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include <windows.h>
#pragma comment(lib,"ws2_32.lib")

#define DEFAULT_PORT 5051//FOR SEND
#define DEFAULT_PORTRECV 5052 //FOR RECV
#define BUFFER_LENGTH 1024

struct P
{
	SOCKET *sClient;
	struct sockaddr_in *ser;
};


DWORD WINAPI ThreadProc1(LPVOID lpParam) 
{
	//printf("threadproc1 is running! ");


	int iRecv;
	char recv_buf[1030];
	int iLen;

	SOCKET sClient;
	struct sockaddr_in ser;
	sClient=*((struct P *)lpParam)->sClient;
	ser=*((struct P *)lpParam)->ser;

	
	iLen=sizeof(ser);
	while(1)
	{
		iRecv=recvfrom(sClient,recv_buf,sizeof(recv_buf),0,(struct sockaddr*)&ser,&iLen);
		if(iRecv==SOCKET_ERROR)
		{printf("recvfrom()Failed.:%d\n",WSAGetLastError());return 0;}
		else if(iRecv==0) return 0;
		else
		{
			printf("\n----------------------\n");
			//printf("Accepted client IP:[%s],port:[%d]\n",inet_ntoa(ser.sin_addr),ntohs(ser.sin_port));  
			printf("%s\n",recv_buf);
			printf("----------------------\n");
			printf("请输入内容:");
		}

	}

	return 0;
}

void main(int argc,char *argv[])
{
	WSADATA wsaData;
	SOCKET sClient;
	int iPort=DEFAULT_PORT;

	int iLen;

	int iSend;
	int iRecv;

	char send_buf[1000]="newuser";

	char recv_buf[BUFFER_LENGTH];

	struct sockaddr_in ser;

	if(argc<2){printf("usage:client [server IP address]\n");return;}

	memset(recv_buf,0,sizeof(recv_buf));
	if(WSAStartup(MAKEWORD(2,2),&wsaData)!=0)
	{
		printf("Failed to load winsock.\n");
		return ;
	}

	//建立服务器信息 发送到目标机器  
	ser.sin_family=AF_INET;
	ser.sin_port=htons(iPort);
	ser.sin_addr.s_addr=inet_addr(argv[1]);

	sClient=socket(AF_INET,SOCK_DGRAM,0);
	if(sClient==INVALID_SOCKET)
	{printf("socket()Failed:%d\n",WSAGetLastError());return;}

	iLen=sizeof(ser);

	struct sockaddr_in cser;

	cser.sin_family=AF_INET;
	cser.sin_port=htons(DEFAULT_PORTRECV);
	cser.sin_addr.s_addr=htonl(INADDR_ANY);

	if(bind(sClient,(LPSOCKADDR)&cser,sizeof(cser))==SOCKET_ERROR)
	{printf("bind()Faild:%d\n",WSAGetLastError());return ;}

	/*
	cser.sin_family=AF_INET;
	cser.sin_port=htons(iPort);
	cser.sin_addr.s_addr=htonl(INADDR_ANY);

	if(bind(sSocket,(LPSOCKADDR)&ser,sizeof(ser))==SOCKET_ERROR)
	{printf("bind()Faild:%d\n",WSAGetLastError());return;}
	*/
	char name[100];
	printf("请输入您的姓名:");
	scanf("%s",&name);
	if(strcmp(name,"exit")==0)return;
	strcat(send_buf,name);
	iSend=sendto(sClient,send_buf,sizeof(send_buf),0,(struct sockaddr*)&ser,iLen);


	//CreateThread(            
	//	NULL,              // default security attributes           
	//	0,                 // use default stack size              
	//	(LPTHREAD_START_ROUTINE )ThreadProc1,        // thread function             
	//	argv[1],             // argument to thread function             
	//	0,                 // use default creation flags             
	//	(LPDWORD)&ThreadProc1);           // returns the thread identifier 

	struct P * point;
	point=(struct P *)malloc(sizeof(struct P));
	point->sClient=&sClient;
	point->ser=&ser;

	CreateThread(            
		NULL,              // default security attributes           
		0,                 // use default stack size              
		ThreadProc1,        // thread function             
		(LPVOID)point,             // argument to thread function             
		0,                 // use default creation flags             
		NULL);           // returns the thread identifier 


	while(1)
	{
		char says[1000];
		printf("请输入内容:");
		scanf("%s",&says);

		strcpy(send_buf,"newsays");
		strcat(send_buf,says);

		iSend=sendto(sClient,send_buf,sizeof(send_buf),0,(struct sockaddr*)&ser,iLen);
		if(iSend==SOCKET_ERROR)
		{printf("sendto()Failed:%d\n",WSAGetLastError());return;}
		else if(iSend==0) return;
		else 
		{
			;//printf("sendto() mubiao succeeded .\n");
		}
		if(strcmp(says,"exit")==0){printf("exited!\n");break;}



		/*
		iRecv=recvfrom(sClient,recv_buf,sizeof(recv_buf),0,(struct sockaddr*)&ser,&iLen);
		if(iRecv==SOCKET_ERROR)
		{printf("recvfrom()Failed.:%d\n",WSAGetLastError());return;}
		else if(iRecv==0) return;
		else
		{
		printf("recvfrom():%s\n",recv_buf);
		printf("----------------------\n");
		}
		*/
	}
	closesocket(sClient);
	WSACleanup();
}







  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值