gpt4 book ai didi

在Linux上的多线程C服务器中创建新的文件描述符

转载 作者:行者123 更新时间:2023-11-30 19:04:47 25 4
gpt4 key购买 nike

将我在学校学到的知识应用到一个爱好项目中,但我对网络编程还很陌生。我正在 Linux 上使用 C 服务器设计一个简单的多用户文本游戏。我有一个简单的线程 C 回显服务器,使用 NPTL( native POSIX 线程库)进行传入连接。我想通过在每个连接上打开一个新的文件描述符来避免竞争和死锁情况,以便它们可以访问设备等的数据库项而无需使用锁。我可以使用 select() 来轮询每个线程连接吗?这对于最佳实践有意义吗?

我试图在 Beej 的《网络编程指南》中找到示例,但找不到。

编辑:

这是我的回显服务器的基础知识:

// .. pick a port on startup
// initial socket creation
lsock = socket(AF_INET,SOCK_STREAM,0);
// ... error handling
sname.sin_family = AF_INET;
sname.sin_addr.s_addr = INADDR_ANY;
sname.sin_port = htons( port );
// binding the socket
while(client_sock=accept(lsock,(struct sockaddr*)&client,(socklen_t*)&c))
{
puts("New connection accepted");

pthread_t cthread;
new_sock = malloc(1);
*new_sock = client_sock;

if( pthread_create( &cthread , NULL , clientHandler , (void*) new_sock) < 0)
{
perror("Error: Thread creation");
return 1;
}

puts("Handler assigned");
}

void *clientHandler(void *socket_desc)
{
//Get the socket descriptor
int sock = *(int*)socket_desc;
int n;

char sendBuff[100], client_message[2000];

while((n=recv(sock,client_message,2000,0))>0)
{
send(sock,client_message,n,0);
}
close(sock);
if(n==0)
{
puts("Client disconnected");
}
else
{
perror("recv failed");
}
return 0;
}

这是我的计划是在下面的基本房间系统和播放器系统上的回声服务器上实现:

struct pollfd pdata[MAXPLAY+1];

struct _player{
obj o;
int id,state,file_desc,roomNum;
void(*ip)(plr *p, char ch);
char name[16],op[MAXBUF],line[128];
struct pollfd *p;
int HP,ATK;
plr *target;
};


void init_player(player *p){
p->HP=10;
p->ATK=1;
p->target=NULL;
}

#define playerLloop(p) for(i=0,p=players;i<MAXPLAY;i++,p++)

if(p->state==0){
init_plr(p);
p->state=1;
p->name[0]=0;
p->file_desc=rsock; // file descriptor
p->roomNum=0;
// function to initialize names and add to linked list of players
p->ip=new_connect;
// function to send clients a message
sendp(p,"Welcome");
}

一旦我通过客户端处理程序初始化播放器,我就会将它们添加到带有文件描述符的链接列表中。我的问题就在这里;当我有两个单独的线程尝试访问服务器上的对象时,避免任何类型的竞争或死锁情况的最佳方法是什么?我可以通过解析函数处理它以获取客户端输入来解决此问题吗?

如果玩家一尝试打开房间中的一扇门,玩家二就会尝试打开同一扇门;当我通过线程连接读取两个客户端的文件描述符时,如何为这些套接字分配优先级?这可能会导致竞争或死锁情况吗?

我只是很难理解通过线程套接字读取信息的概念。

最佳答案

Would I be able to use select() to poll each of my threaded connections?

select() 用于通过线程高效地服务多个 I/O channel 。您在评论中澄清,您打算为每个客户提供单独的线程。在这种情况下,您不需要 select 来管理客户端连接:每个此类连接都有一个专用于它的整个线程!

您似乎建议每个线程还可以获得它所需的所有其他资源,例如与底层数据库的连接。在这种情况下,是的,只要这些外部资源本质上支持您需要的并发访问类型,您就可以避免在自己的代码中使用锁来保护它们。

Does this make sense for best practices?

每个客户端线程模型是一种相当常见的模型。只要并发客户端数量不是太大就应该没问题。您将需要确保有一种方法可以清理在没有通知的情况下消失的客户端线程。 “太大”的大小取决于每个线程实际执行的工作的细节以及运行该线程的机器的特征。

如果并发客户端的数量增长得足够大,那么您将需要改变您的方法,但我认为您还不需要对此过于担心。保持代码整洁和模块化并避免依赖线程本地数据将有助于在您达到需要时切换到不同的方法。

关于在Linux上的多线程C服务器中创建新的文件描述符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51086706/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com