C语言 C中的多线程服务器/客户端实现
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/21405204/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
multithread server/client implementation in C
提问by Shikhar Deep
I have just started learning basic networking concepts.I am trying to implement a multithread server-client prog in C.but the problem is instead of running multiple windows/terminals/instances for clients,i should use fork() to create children of client.so by creating children of client multiple clients will be created.now each of these child clients will communicate with the server on a thread.
我刚刚开始学习基本的网络概念。我试图在 C 中实现一个多线程服务器 - 客户端程序。但问题是不是为客户端运行多个窗口/终端/实例,我应该使用 fork() 创建客户端的子级.so 通过创建客户端的子客户端将创建多个客户端。现在这些子客户端中的每一个都将在一个线程上与服务器通信。
Earlier i created a similar prog but in that for multiple client you have to open multiple windows for clients and run all of them.
早些时候我创建了一个类似的编,但对于多个客户端,您必须为客户端打开多个窗口并运行所有这些窗口。
I am having trouble where to modify my code (both in server and client ones.I think server one is ok.but i am having no idea where to fork() in client program and what changes should be made).
我在修改我的代码时遇到了麻烦(在服务器和客户端的代码中。我认为服务器一没问题。但我不知道在客户端程序中 fork() 的位置以及应该进行哪些更改)。
Actually i don't want to open multiple windows to run multiple client,thats why i am using fork() to create multiple copies of it.Is there any other way by which i can create multiple clients and connect them to my server prog via threads.
实际上我不想打开多个窗口来运行多个客户端,这就是为什么我使用 fork() 创建它的多个副本。有没有其他方法可以创建多个客户端并将它们连接到我的服务器程序线程。
Server :
服务器 :
// socket server example, handles multiple clients using threads
#include<stdio.h>
#include<string.h> //strlen
#include<stdlib.h> //strlen
#include<sys/socket.h>
#include<arpa/inet.h> //inet_addr
#include<unistd.h> //write
#include<pthread.h> //for threading , link with lpthread
//the thread function
void *connection_handler(void *);
int main(int argc , char *argv[])
{
int socket_desc , client_sock , c , *new_sock;
struct sockaddr_in server , client;
//Create socket
socket_desc = socket(AF_INET , SOCK_STREAM , 0);
if (socket_desc == -1)
{
printf("Could not create socket");
}
puts("Socket created");
//Prepare the sockaddr_in structure
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons( 3000 );
//Bind
if( bind(socket_desc,(struct sockaddr *)&server , sizeof(server)) < 0)
{
//print the error message
perror("bind failed. Error");
return 1;
}
puts("bind done");
//Listen
listen(socket_desc , 3);
//Accept and incoming connection
puts("Waiting for incoming connections...");
c = sizeof(struct sockaddr_in);
c=sizeof(struct sockaddr_in);
while(client_sock=accept(socket_desc,(struct sockaddr*)&client,(socklen_t*)&c))
{
puts("Connection accepted");
pthread_t sniffer_thread;
new_sock = malloc(1);
*new_sock = client_sock;
if( pthread_create( &sniffer_thread , NULL , connection_handler , (void*) new_sock) < 0)
{
perror("could not create thread");
return 1;
}
puts("Handler assigned");
}
if (client_sock < 0)
{
perror("accept failed");
return 1;
}
return 0;
}
/*
This will handle connection for each client
*/
void *connection_handler(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;
}
Client:
客户:
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <unistd.h>
#define MAX_SIZE 50
int main()
{
int sock_desc;
struct sockaddr_in serv_addr;
char sbuff[MAX_SIZE],rbuff[MAX_SIZE];
if((sock_desc = socket(AF_INET, SOCK_STREAM, 0)) < 0)
printf("Failed creating socket\n");
bzero((char *) &serv_addr, sizeof (serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
serv_addr.sin_port = htons(3000);
if (connect(sock_desc, (struct sockaddr *) &serv_addr, sizeof (serv_addr)) < 0) {
printf("Failed to connect to server\n");
return -1;
}
printf("Connected successfully - Please enter string\n");
while(fgets(sbuff, MAX_SIZE , stdin)!=NULL)
{
send(sock_desc,sbuff,strlen(sbuff),0);
if(recv(sock_desc,rbuff,MAX_SIZE,0)==0)
printf("Error");
else
fputs(rbuff,stdout);
bzero(rbuff,MAX_SIZE);//to clean buffer-->IMP otherwise previous word characters also came
}
close(sock_desc);
return 0;
}
回答by sujin
You can create multiple clients using thread. Create a separate thread for each client and then from thread handler connect to the server. I am not sure if it is a good way or not.
您可以使用线程创建多个客户端。为每个客户端创建一个单独的线程,然后从线程处理程序连接到服务器。我不确定这是否是一个好方法。
Code:
代码:
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <unistd.h>
#define MAX_SIZE 50
#define NUM_CLIENT 5
void *connection_handler(void *socket_desc);
int main()
{
int socket_desc , new_socket , c , *new_sock, i;
pthread_t sniffer_thread;
for (i=1; i<=NUM_CLIENT; i++) {
if( pthread_create( &sniffer_thread , NULL , connection_handler , (void*) i) < 0)
{
perror("could not create thread");
return 1;
}
sleep(3);
}
pthread_exit(NULL);
return 0;
}
void *connection_handler(void *threadid)
{
int threadnum = (int)threadid;
int sock_desc;
struct sockaddr_in serv_addr;
char sbuff[MAX_SIZE],rbuff[MAX_SIZE];
if((sock_desc = socket(AF_INET, SOCK_STREAM, 0)) < 0)
printf("Failed creating socket\n");
bzero((char *) &serv_addr, sizeof (serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
serv_addr.sin_port = htons(8888);
if (connect(sock_desc, (struct sockaddr *) &serv_addr, sizeof (serv_addr)) < 0) {
printf("Failed to connect to server\n");
}
printf("Connected successfully client:%d\n", threadnum);
while(1)
{
printf("For thread : %d\n", threadnum);
fgets(sbuff, MAX_SIZE , stdin);
send(sock_desc,sbuff,strlen(sbuff),0);
if(recv(sock_desc,rbuff,MAX_SIZE,0)==0)
printf("Error");
else
fputs(rbuff,stdout);
bzero(rbuff,MAX_SIZE);
sleep(2);
}
close(sock_desc);
return 0;
}
For understanding purpose, i used sleep.
出于理解目的,我使用了sleep.
REF:
参考:
http://www.amazon.com/UNIX-Network-Programming-Richard-Stevens/dp/0139498761
http://www.amazon.com/UNIX-Network-Programming-Richard-Stevens/dp/0139498761
回答by abligh
Firstly, if you fork(), you will be creating additional processes, not additional threads. To create additional threads, you want to use pthread_create.
首先,如果你fork(),你将创建额外的进程,而不是额外的线程。要创建其他线程,您需要使用pthread_create.
Secondly, as you are a student, the canonical answer here is 'read Stephens'. Not only is this an invaluable tool even for those of us experienced in writing socket I/O routines, but also it contains examples of non-threaded non-forking async I/O, and various ways to add threads and forking to them. I believe the one you want is: http://www.amazon.com/Programming-Environment-Addison-Wesley-Professional-Computing/dp/0321637739(chapter 14 if memory serves). This should be in your college library.
其次,作为一名学生,这里的规范答案是“阅读斯蒂芬斯”。即使对于我们这些在编写套接字 I/O 例程方面有经验的人来说,这不仅是一个非常宝贵的工具,而且它还包含非线程非分叉异步 I/O 的示例,以及向它们添加线程和分叉的各种方法。我相信您想要的是:http: //www.amazon.com/Programming-Environment-Addison-Wesley-Professional-Computing/dp/0321637739(如果没记错的话,请参阅第 14 章)。这应该在你的大学图书馆里。

