17-基于curses的简单网络聊天程序(1)

   使用多进程实现多任务

程序移植时需要注意ziji电脑的IP地址与端口,


案例:

客户端:

1. 建立socket

2. 连接到服务器

3. 创建curses界面

4. 创建子进程

5. 在父进程中,输入,发送聊天信息

6. 在子进程中,接收服务器传递的信息(服务器把接收的信息进行广播)。


// chatCient.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <curses.h>
#include <unistd.h>
#include <signal.h>
/*
一般写curses 的程序,就不要用printf来进行输出了
*/

WINDOW *winfo,*wmsg;
int fd;
int r;
struct sockaddr_in dr;

int initSocket(); // 创建文件描述符,绑定IP地址
void initUI(); // 初始化字符界面
void destroy();

void deal(int s)
{
	int status;
	wait(&status);
	destroy();
	exit(-1);
}

main()
{
	initUI();
	
	r = initSocket();
	if(r==-1) exit(-1);
	signal(SIGCHLD,deal);
	
	if(fork()) // 父进程
	{
		// 输入,发送聊天信息
		char buf[256];
		while(1)
		{

			mvwgetstr(wmsg,1,1,buf);
			wmove(wmsg,1,1);
			clrtoeol();
			//wclrtobot(wmsg);
			wclrtoeol(wmsg);
			send(fd,buf,strlen(buf),0);
			refresh();
			wrefresh(wmsg);
			wrefresh(winfo);
			
		}
	}
	else   /// 子进程,接收来自服务器的数据,并显示
	{
		char buf[256];
		int line = 1; // 行数初始化显示在第一行
		while(1)
		{
		    
			r = recv(fd,buf,255,0);
			if(r == -1) break;
			if(r == 0) break;

			buf[r] = 0;
			mvwaddstr(winfo,line,1,buf);
			line++;
			if(line >= (LINES-3))
			{
				wclear(winfo);
				line = 1;
				box(winfo,0,0);
			}
			//wclear(wmsg);
			wmove(wmsg,1,1);
			//clrtoeol();
			touchwin(wmsg);
			refresh();
			wrefresh(winfo);
			wrefresh(wmsg);
		}
		exit(-1);
	}
	
	destroy();
}

// 函数调用成功就返回0,调用失败返回-1
int initSocket()
{
	fd = socket(AF_INET,SOCK_STREAM,0);
	if(fd == -1) return -1;
	
	dr.sin_family = AF_INET;
	dr.sin_port = htons(9999);
	dr.sin_addr.s_addr = inet_addr("120.6.20.247");
	
	r = connect(fd,(struct sockaddr*)&dr,sizeof(dr));
	if(r==-1)
	{
		close(fd);
		return -1;
	}
	return 0;
	
}

void initUI()
{
	initscr();
	winfo = derwin(stdscr,(LINES-3),COLS,0,0);
	wmsg = derwin(stdscr,3,COLS,LINES-3,0);
	box(winfo,0,0);
	box(wmsg,0,0);
	refresh();
	wrefresh(winfo);
	wrefresh(wmsg);

}
void destroy()
{
	close(fd);
	endwin();
}

服务器程序:

       建立socket

       绑定地址

       监听

       循环接收客户连接

      为客户创建子进程

      在子进程接收该客户的数据,并进行广播。


/// chatserver.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/mman.h>

int sfd;
int *fds; // 存放存放客户代理描述符,使用共享内存
int idx =0; // 客户在数组中的下标
struct sockaddr_in dr; // 客户ID
int r;


main()
{
// 1. 建立服务器socket
	fds = mmap(0,4*100,PROT_READ | PROT_WRITE,MAP_ANONYMOUS | MAP_SHARED,0,0);
	bzero(fds,sizeof(fds));
	
	sfd = socket(AF_INET,SOCK_STREAM,0);
	if(sfd == -1) printf("socket err:%m\n"),close(sfd),exit(-1);
	printf("socket OK!\n");
// 2. 绑定地址
	dr.sin_family = AF_INET;
	dr.sin_port = htons(9999);
	dr.sin_addr.s_addr = inet_addr("120.6.20.247");
	
	r = bind(sfd,(struct sockaddr*)&dr,sizeof(dr));
	if(r==-1) printf("bind err:%m\n"),exit(-1);
	printf("bind OK!\n");
// 3. 监听
	r = listen(sfd,5); //队列中可以容纳的未处理连接的最大数目做出限制。常用为5
	if(r == -1) printf("listen err:%m\n"),exit(-1);
	printf("listen OK!\n"); 
// 4. 循环接收客户连接
	while(1)
	{
		fds[idx] = accept(sfd,0,0);
		if(fds[idx] == -1) break;
		printf("有客户连接:%d\n",fds[idx]);
		// 5. 建立一个子进程
		if(fork())
		{
			idx++;
			continue;
		}
		else
		{
			// 6. 子进程任务: 接收客户信息并且广播
			char buf[256];
			int i;
			printf("开始接收客户%d数据\n",fds[idx]);
			while(1)
			{
				// 接收客户数据
				r = recv(fds[idx],buf,255,0);
				//printf("%d\n",r);
				if(r == 0)
				{
					printf("客户%d退出!\n",fds[idx]);
					close(fds[idx]);
					fds[idx] = 0;
					break;
				}
				if( r== -1)
				{
					printf("网络故障!\n");
					close(fds[idx]);
					fds[idx] = 0;
					break;
				}
				buf[r] = 0;
				printf("来自客户%d的数据:%s\n",fds[idx],buf);
				// 广播
				for(i=0; i<100;++i)
				{
					if(fds[i] > 0)
					{
						send(fds[i],buf,r,0);
					}
				}
				
			}
			exit(0);
		}
	}
    close(sfd);
}


总结:
           多个用户连接并不能全部广播到每个用户,多进程由于进程的资源结构独立,

新进程的文件描述符号的环境在老进程中无法访问。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Windows-curses是一个用于在Windows平台上使用curses库的Python包。由于curses库本身是为Linux平台设计的,所以在Windows平台上使用时需要安装windows-curses包。 要在Windows上安装windows-curses包,你可以按照以下步骤进行操作: 1. 首先,确定你已经安装了Python,并且在命令行中可以使用pip命令。 2. 在命令行中运行`pip install windows-curses`命令,这将自动从Python Package Index(PyPI)下载并安装windows-curses包。 3. 如果在安装过程中出现版本报错或者出现其他问题,你可以尝试更新pip并检查你的Python版本是否与安装包兼容。 通过以上步骤,你就可以成功安装windows-curses包,并在Windows平台上使用curses库了。请注意,由于Windows和Linux平台上的curses库的实现方式存在差异,因此一些在Linux上可用的功能可能在Windows上不可用。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [Windows下安装Curses库 + 查看pip所支持whl版本](https://blog.csdn.net/Firewall5788/article/details/120425461)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [解决windows下python--curses报错问题](https://download.csdn.net/download/qq_32727193/10109219)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值