1、基于TCP(面向连接)的socket编程,分为客户端和服务器端。
客户端的流程如下:
(1)创建套接字(socket)
(2)设置要连接的服务器的IP地址和端口信息
(3)向服务器发出连接请求(connect)
(4)和服务器端进行通信(send/recv或read/write)
(5)关闭套接字(close)
服务器端的流程如下:
(1)创建套接字(socket)
(2)将套接字绑定到一个本地地址和端口上(bind)
(3)将套接字设为监听模式,准备接收客户端请求(listen)
(4)等待客户请求到来;当请求到来后,接受连接请求,返回一个新的对应于此次连接的套接字(accept)
(5)用返回的套接字和客户端进行通信(send/recv或read/write)
(6)返回,等待另一个客户请求。
(7)关闭套接字。
2、服务器模型
1、循环服务器
2、并发服务器
3、I/O多路复用
3、事例代码
1、循环服务器
//server.c #include "server_c.h" int main(int argc, char const *argv[]) { pid_t ser_fd; int i,max; if(-1 == (ser_fd=fork())){ perror("fork"); exit(-1); } if(ser_fd != 0){ exit(0); } if(-1 == setsid()){ perror("setsid"); exit(-1); } if(-1 == chdir("/tmp")){ perror("chdir"); } umask(0); max = getdtablesize(); for(i=0;i < max;i++){ close(i); } int s_fd,c_fd; socklen_t len=sizeof(struct sockaddr_in); struct sockaddr_in server={0},client={0}; bzero(&server,sizeof(server)); if(-1 == (s_fd=(socket(AF_INET,SOCK_STREAM,0)))){ perror("socket"); exit(-1); } server.sin_family = AF_INET; server.sin_port = htons(8888); server.sin_addr.s_addr = inet_addr("0.0.0.0"); if(-1 == bind(s_fd,(struct sockaddr*)&server,sizeof(server))){ perror("bind"); exit(-1); } if(-1 == listen(s_fd,MAXBACKLOG)){ perror("listen"); exit(-1); } while(1){ bzero(&client,sizeof(client)); if(-1 == (c_fd=accept(s_fd,(struct sockaddr*)&client,&len))){ perror("accept"); exit(-1); } calc(c_fd); close(c_fd); } return 0; }
2、循环服务器
//server.c #include "server_c.h" void fun(int sig) { if(sig == SIGCHLD){ waitpid(-1,NULL,0); } } int main(int argc, char const *argv[]) { pid_t ser_fd; int i,max; if(-1 == (ser_fd=fork())){ perror("fork"); exit(-1); } if(ser_fd != 0){ exit(0); } if(-1 == setsid()){ perror("setsid"); exit(-1); } if(-1 == chdir("/tmp")){ perror("chdir"); } umask(0); max = getdtablesize(); for(i=0;i < max;i++){ close(i); } int s_fd,c_fd; pid_t pid; socklen_t len=sizeof(struct sockaddr_in); struct sockaddr_in server={0},client={0}; bzero(&server,sizeof(server)); if(-1 == (s_fd=(socket(AF_INET,SOCK_STREAM,0)))){ perror("socket"); exit(-1); } server.sin_family = AF_INET; server.sin_port = htons(8888); server.sin_addr.s_addr = inet_addr("0.0.0.0"); if(-1 == bind(s_fd,(struct sockaddr*)&server,sizeof(server))){ perror("bind"); exit(-1); } if(-1 == listen(s_fd,MAXBACKLOG)){ perror("listen"); exit(-1); } signal(SIGCHLD,fun); while(1){ bzero(&client,sizeof(client)); if(-1 == (c_fd=accept(s_fd,(struct sockaddr*)&client,&len))){ perror("accept"); exit(-1); } if(-1 == (pid=fork())){ perror("fork"); exit(-1); } if(0 == pid){ calc(c_fd); close(c_fd); exit(0); }else{ close(c_fd); } } return 0; }3、I/O多路复用
//server.c #include "server_c.h" int main(int argc, char const *argv[]) { pid_t ser_fd; int i,max; if(-1 == (ser_fd=fork())){ perror("fork"); exit(-1); } if(ser_fd != 0){ exit(0); } if(-1 == setsid()){ perror("setsid"); exit(-1); } if(-1 == chdir("/tmp")){ perror("chdir"); } umask(0); max = getdtablesize(); for(i=0;i < max;i++){ close(i); } int s_fd,c_fd; pid_t pid; socklen_t len=sizeof(struct sockaddr_in); struct sockaddr_in server={0},client={0}; bzero(&server,sizeof(server)); if(-1 == (s_fd=(socket(AF_INET,SOCK_STREAM,0)))){ perror("socket"); exit(-1); } server.sin_family = AF_INET; server.sin_port = htons(8888); server.sin_addr.s_addr = inet_addr("0.0.0.0"); if(-1 == bind(s_fd,(struct sockaddr*)&server,sizeof(server))){ perror("bind"); exit(-1); } if(-1 == listen(s_fd,MAXBACKLOG)) { perror("listen"); exit(-1); } fd_set reads; FD_ZERO(&reads); FD_SET(s_fd,&reads); fd_set tem_fds = reads; int max_fd = s_fd; while(1){ reads = tem_fds; if(-1 == select(max_fd+1,&reads,NULL,NULL,NULL)){ perror("select"); exit(-1); } if(FD_ISSET(s_fd,&reads)){ bzero(&client,sizeof(client)); if(-1 == (c_fd=accept(s_fd,(struct sockaddr*)&client,&len))){ perror("accept"); exit(-1); } FD_SET(c_fd,&tem_fds); max_fd = (max_fd > c_fd ? max_fd : c_fd); } else{ int i; for (i = 0; i < max_fd+1; ++i) { if(FD_ISSET(i,&reads)&& i != s_fd){ calc(i); } } } } return 0; }4、其他相关程序
//server_c.c
#include "server_c.h"
void creat_stack(TSq *t)
{
*t=NULL;
}
int empty_stack(TSq t)
{
return t==NULL;
}
int get_stack_top(TSq t)
{
if(empty_stack(t)){
printf("Stack is empty!\n");
exit(0);
}
return t->data;
}
void push(TSq *t,data_t data)
{
TSq q;
q=(TSq)malloc(sizeof(Sq));
q->data=data;
q->next=*t;
*t=q;
}
int pop(TSq *t)
{
data_t data;
if(empty_stack(*t)){
printf("Stack is empty!\n");
return;
}
data=(*t)->data;
*t=(*t)->next;
return data;
}
void display(TSq t)
{
TSq p;
p=t;
while(p!=NULL){
printf("%c ",p->data);
p=p->next;
}
}
void calculate_arith(char *str,char *result)
{
TSq record,symbol;
char *p;
int i,a,b,c1;
creat_stack(&record);
creat_stack(&symbol);
for(p=str;*p!=‘\0‘;p++){
c1 = *p;
if(*p >= ‘0‘ && *p <= ‘9‘)
{
c1=atoi(p);
while(*(++p)>=‘0‘ && *p <= ‘9‘);
p--;
}
switch(c1){
case ‘+‘:
{
int a,b,c;
if(empty_stack(symbol)){
push(&symbol,c1);
}
else{
while(!empty_stack(symbol)&&(c=get_stack_top(symbol))!=‘(‘){
c=pop(&symbol);
switch(c){
case ‘+‘:
{
a=pop(&record);
b=pop(&record);
push(&record,a+b);
}
break;
case ‘-‘:
{
a=pop(&record);
b=pop(&record);
push(&record,b-a);
}
break;
case ‘*‘:
{
a=pop(&record);
b=pop(&record);
push(&record,a*b);
}
break;
case ‘/‘:
{
a=pop(&record);
b=pop(&record);
push(&record,b/a);
}
break;
default:
{
printf("%c is Unknow symbol!\n",c);
exit(-1);
}
break;
}
}
push(&symbol,c1);
}
}
break;
case ‘-‘:
{
int a,b,c;
if(empty_stack(symbol)){
push(&symbol,c1);
}
else{
while(!empty_stack(symbol)&&(c=get_stack_top(symbol))!=‘(‘){
c=pop(&symbol);
switch(c){
case ‘+‘:
{
a=pop(&record);
b=pop(&record);
push(&record,a+b);
}
break;
case ‘-‘:
{
a=pop(&record);
b=pop(&record);
push(&record,b-a);
}
break;
case ‘*‘:
{
a=pop(&record);
b=pop(&record);
push(&record,a*b);
}
break;
case ‘/‘:
{
a=pop(&record);
b=pop(&record);
push(&record,b/a);
}
break;
default:
{
printf("%c is Unknow symbol!\n",c);
exit(-1);
}
break;
}
}
push(&symbol,c1);
}
}
break;
case ‘*‘:
{
int a,b,c;
if(empty_stack(symbol)){
push(&symbol,c1);
}
else{
while(!empty_stack(symbol)&&(c=get_stack_top(symbol))==‘*‘&&(c=get_stack_top(symbol))==‘/‘){
c=pop(&symbol);
switch(c){
case ‘*‘:
{
a=pop(&record);
b=pop(&record);
push(&record,a*b);
}
break;
case ‘/‘:
{
a=pop(&record);
b=pop(&record);
push(&record,b/a);
}
break;
default:
{
printf("%c is Unknow symbol!\n",c);
exit(-1);
}
break;
}
}
push(&symbol,c1);
}
}
break;
case ‘/‘:
{
int a,b,c;
if(empty_stack(symbol)){
push(&symbol,c1);
}
else{
while(!empty_stack(symbol)&&(c=get_stack_top(symbol))==‘*‘&&(c=get_stack_top(symbol))==‘/‘){
c=pop(&symbol);
switch(c){
case ‘*‘:
{
a=pop(&record);
b=pop(&record);
push(&record,a*b);
}
break;
case ‘/‘:
{
a=pop(&record);
b=pop(&record);
push(&record,b/a);
}
break;
default:
{
printf("%c is Unknow symbol!\n",c);
exit(-1);
}
break;
}
}
push(&symbol,c1);
}
}
break;
case ‘(‘:
{
push(&symbol,‘(‘);
}
break;
case ‘)‘:
{
int a,b,c;
while((c=pop(&symbol))!=‘(‘){
switch(c){
case ‘+‘:
{
a=pop(&record);
b=pop(&record);
push(&record,a+b);
}
break;
case ‘-‘:
{
a=pop(&record);
b=pop(&record);
push(&record,b-a);
}
break;
case ‘*‘:
{
a=pop(&record);
b=pop(&record);
push(&record,a*b);
}
break;
case ‘/‘:
{
a=pop(&record);
b=pop(&record);
push(&record,b/a);
}
break;
default:
{
printf("%c is Unknow symbol!\n",c);
exit(-1);
}
break;
}
}
}
break;
default:
{
push(&record,c1);
}
break;
}
}
while(!empty_stack(symbol)){
c1=pop(&symbol);
switch(c1){
case ‘+‘:
{
a=pop(&record);
b=pop(&record);
push(&record,a+b);
}
break;
case ‘-‘:
{
a=pop(&record);
b=pop(&record);
push(&record,b-a);
}
break;
case ‘*‘:
{
a=pop(&record);
b=pop(&record);
push(&record,a*b);
}
break;
case ‘/‘:
{
a=pop(&record);
b=pop(&record);
push(&record,b/a);
}
break;
default:
{
printf("%c is Unknow symbol!\n",c1);
exit(-1);
}
break;
}
}
sprintf(result,"计算结果为:\n %s = %d\n",str,pop(&record));
}
void calc(int c_fd)
{
char buf[200],result[200];
while(1){
bzero(buf,200);
bzero(result,50);
read(c_fd,buf,200);
if(0 == strncmp(buf,"quit",4)){
break;
}
calculate_arith(buf,result);
write(c_fd,result,200);
}
}
//server_c.h #ifndef _SERVER_C_H_ #define _SERVER_C_H_ #include <stdio.h> #include <strings.h> #include <sys/types.h> #include <sys/socket.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> #include <netinet/in.h> #include <arpa/inet.h> #include <time.h> #include <sys/wait.h> #define MAXBACKLOG 100 #define data_t int typedef struct stack { /* data */ int data; struct stack *next; }Sq,*TSq; void creat_stack(TSq *t); int empty_stack(TSq t); int get_stack_top(TSq t); void push(TSq *t,data_t data); int pop(TSq *t); void display(TSq t); void calculate_arith(char *str,char *result); void calc(int c_fd); #endif
//client.c #include <stdio.h> #include <strings.h> #include <sys/types.h> #include <sys/socket.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> #include <netinet/in.h> #include <arpa/inet.h> #include <time.h> #include <sys/wait.h> #include <pthread.h>
int main(int argc, char const *argv[]) { if(3 != argc){ printf("Usage: %s <IP> <Port>\n",argv[0]); exit(-1); } int c_fd; char buf[200]; struct sockaddr_in server; bzero(&server,sizeof(struct sockaddr_in)); if(-1 == (c_fd=(socket(AF_INET,SOCK_STREAM,0)))){ perror("socket"); exit(-1); } server.sin_family = AF_INET; server.sin_port = htons(atoi(argv[2])); server.sin_addr.s_addr = inet_addr(argv[1]); if(-1 == connect(c_fd,(struct sockaddr*)&server,sizeof(struct sockaddr_in))){ perror("connect"); exit(-1); } while(1){ bzero(buf,200); printf("输入数学表达式:"); fflush(stdout); gets(buf); write(c_fd,buf,200); if(0 == strncmp(buf,"quit",4)){ printf("quit\n"); exit(0); } bzero(buf,200); read(c_fd,buf,200); printf("%s",buf); } return 0; }6、多线程并发服务器
//server.c #include "server_c.h" void* compute(void *arg) { int c_fd = *((int *)arg); //printf("pthread %d created!\n"); calc(c_fd); close(c_fd); pthread_exit(NULL); } int main(int argc, char const *argv[]) { pid_t ser_fd; int i,max; if(-1 == (ser_fd=fork())){ perror("fork"); exit(-1); } if(ser_fd != 0){ exit(0); } if(-1 == setsid()){ perror("setsid"); exit(-1); } if(-1 == chdir("/tmp")){ perror("chdir"); } umask(0); max = getdtablesize(); for(i=0;i < max;i++){ close(i); } int s_fd,c_fd; pid_t pid; socklen_t len=sizeof(struct sockaddr_in); struct sockaddr_in server={0},client={0}; bzero(&server,sizeof(server)); if(-1 == (s_fd=(socket(AF_INET,SOCK_STREAM,0)))){ perror("socket"); exit(-1); } server.sin_family = AF_INET; server.sin_port = htons(8888); server.sin_addr.s_addr = inet_addr("0.0.0.0"); if(-1 == bind(s_fd,(struct sockaddr*)&server,sizeof(server))){ perror("bind"); exit(-1); } if(-1 == listen(s_fd,MAXBACKLOG)){ perror("listen"); exit(-1); } while(1){ bzero(&client,sizeof(client)); if(-1 == (c_fd=accept(s_fd,(struct sockaddr*)&client,&len))){ perror("accept"); exit(-1); } pthread_t thread; pthread_create(&thread,NULL,compute,&c_fd); } return 0; }运行结果:
原文:http://blog.csdn.net/huangbo_embed/article/details/19925583