给群里朋友写的 . *nix 下:
一个多进程 一个多线程 , 没太多意义的代码 ,只是简单收发, 没有处理粘包这一类问题,util.h中有实现;
util.h
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define EPOLL_SIZE 64
#define PORT 9988
#define BACKLOG 10
#define MAXLINE 4096
#define SA struct sockaddr
ssize_t readn(int fd , void *ptr, size_t n)
{
size_t left = n;
char * p = (char *)ptr;
int nread = 0;
while (left > 0){
if((nread = read(fd,p,left)) < 0){
if(errno == EINTR)
nread = 0;
else
return -1;
}
else if(nread == 0)
break;
left -= nread;
p += nread;
}
return n - left;
}
ssize_t writen(int fd , void * ptr , size_t n)
{
size_t left = n;
char * p = (char*)ptr;
int nwrite = 0;
while( left > 0){
if((nwrite = write(fd,p,left)) <= 0){
if(errno == EINTR && nwrite < 0)
nwrite = 0;
else
return -1;
}
left -= nwrite;
p += nwrite;
}
return n - left;
}
int conn_timeout(int sockfd , const struct sockaddr_in * sin, socklen_t socklen, int secs)
{
int old_flag = fcntl(sockfd,F_GETFL,0);
if( fcntl(sockfd,F_SETFL,old_flag|O_NONBLOCK) < 0){
perror("fcntl failed");
return -1;
}
int ret = 0;
if((ret = connect(sockfd,(SA*)&sin,socklen)) < 0){
if(errno != EINPROGRESS){
perror("connect error");
return -1;
}
}
if(0 == ret)
goto done;
fd_set rset,wset;
FD_ZERO(&rset);
FD_SET(sockfd,&rset);
wset = rset;
struct timeval timeout;
timeout.tv_sec= secs;
timeout.tv_usec = 0;
ret = select(sockfd+1,&rset,&wset,NULL,secs?&timeout:NULL);
if(ret < 0){
perror("select error");
return -1;
}
else if( 0 == ret){
close(sockfd);
return -1;
}
if(!(FD_ISSET(sockfd,&rset) || FD_ISSET(sockfd,&wset))){
return -1;
}
done:
fcntl(sockfd,F_SETFL,old_flag);
return 0;
}
多进程:
#include "util.h"
// sig handler;
void wait_children(int sig)
{
while ( waitpid(-1,0,WNOHANG) > 0 );
}
int main(int argc, char ** argv)
{
signal(SIGCHLD , wait_children);
//init socket
int listenfd = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in serv_addr , clt_addr;
memset(&serv_addr ,0, sizeof(serv_addr));
memset(&clt_addr ,0, sizeof(clt_addr));
serv_addr.sin_port = PORT;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_family = AF_INET;
if ( bind(listenfd , (SA *)&serv_addr, sizeof(serv_addr)) < 0 ){
perror("bind");
return 0;
}
if( listen(listenfd ,BACKLOG) < 0){
perror("listen");
return 0;
}
socklen_t clt_len = 0;
int connfd = -1;
pid_t pid = 0;
while(1){
clt_len = sizeof(clt_addr);
connfd = accept(listenfd,(SA*)&clt_addr, &clt_len);
pid = fork();
if( pid > 0 ){
//parent
close(connfd);
}
else if(0 == pid ){
//child
close(listenfd);
char buff[20];
int len = 0;
while(1) {
len = read(connfd, buff, 19);
if(len < 0){
perror("read error");
break;
}
else if ( 0 == len){
printf(" clt sock : %d , closed!\n" , connfd);
break;
}
buff[len] = 0;
printf("serv: read data: %s\n" , buff);
write(connfd, buff,len);
}
close(connfd);
return 0;
}
else
{
//如果失败了
perror("fork");
close(connfd);
continue;
}
}
return 0;
}
多线程:
#include "util.h"
typedef struct __client_info{
int clientfd;
pthread_t tid;
struct sockaddr_in si;
} client_info;
static void * client_thread(void*);
static int copy_client_info(client_info *,struct sockaddr_in *);
int main(int argc ,char ** argv)
{
int sockfd = socket(AF_INET,SOCK_STREAM,0);
int clientfd = 0;
struct sockaddr_in si = {0} , client = {0};
si.sin_family = AF_INET;
si.sin_addr.s_addr = INADDR_ANY;
si.sin_port = htons(PORT);
socklen_t addr_len = sizeof(si);
if(bind(sockfd,(SA*)&si,addr_len) < 0){
perror("bind failed");
return 0;
}
listen(sockfd,BACKLOG);
socklen_t client_len = 0;
while(1){
client_len = sizeof(client);
clientfd = accept(sockfd,(SA*)&client,&client_len);
client_info *pinfo = malloc(sizeof(client_info));
pinfo->clientfd = clientfd;
copy_client_info(pinfo,&client);
pthread_create(&pinfo->tid,NULL,client_thread,pinfo);
}
return 0;
}
static int copy_client_info(client_info *target,struct sockaddr_in *src)
{
if(!target || !src)
return -1;
target->si.sin_port = src->sin_port;
target->si.sin_addr.s_addr = src->sin_addr.s_addr;
target->si.sin_family = src->sin_family;
return 0;
}
static void * client_thread(void * param)
{
pthread_detach(pthread_self());
client_info * info = (client_info*)param;
char ip[16] = {0} ;
ssize_t iplen = sizeof(ip);
char buf[MAXLINE] = {0};
printf("connect from : %s ,port:%d ,clientfd:%d, tid:%ld\n",
inet_ntop(AF_INET,&info->si.sin_addr.s_addr,ip,iplen)
,ntohs(info->si.sin_port),info->clientfd,info->tid);
int nread = 0;
while(1){
nread = read(info->clientfd,buf,MAXLINE);
if(nread<=0){
break;
}
if(buf[0] == 'q') break;
write(info->clientfd,buf,nread);
}
close(info->clientfd);
free(info);
puts("a client quit");
}