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