多进程多线程TCP服务器
来源:互联网 发布:java 文件base64编码 编辑:程序博客网 时间:2024/06/07 00:25
在TCP/IP协议中,“IP地址+TCP或UDP端口号”唯一标识网络通讯中的一个进程,“IP地址+端口号”称为(套接字)socket。在TCP协议中,建立连接的两个进程各自有一个socket来标识,这两个socket组成的socket pair就唯一标识一个连接。
TCP/IP协议最早在BSD UNIX上实现,为TCP/IP协议设计的应用层编程接口称为socket API。
此处使用socket API应用层编程接口来实现多进程多线程的TCP服务器。
接口函数如下:
- 创建套接字
参数:
domain:有以下参数可选IPv4使用AF_INET
type:服务的类型:TCP为SOCK_STREAM,UDP为SOCK_DRAM
protocol:一般默认为0.
返回值:成功返回文件描述符,失败-1. - 套接字绑定:填充网络
参数:
sockfd:创建的文件描述符(套接字)
addrlen:结构体长度
addr:结构体类型指针,其结构体为(在传参时需强制类型转换):
struct sockaddr_in{ sin_family; //IPv4为AF_INET sin_port;//端口号 sin_addr;//IP地址 sin_pad;//填充字段 };
套接字监听,是否有other连接自己
参数:
sockfd:套接字文件描述符;
backlog:一般数值不能过大,此处代码设为10.
返回值:成功则将套接字改为了监听套接字- 接收other主机连接,保存连接自己主机的信息
参数:
sockfd:监听套接字
addr:输出型参数,结构体保存客户端套接字信息
addrlen:输入输出型参数,传入与传出结构体大小.
返回值:成功返回一个新的套接字,真正用于服务通信等.- 发起连接请求
参数:
sockfd:套接字文件描述符
addr:连接的服务器socket信息;
addrlen:结构体长度.
以上即为实现TCP服务器的主要函数:代码如下
tcp_server.c:
#include <stdio.h>#include <sys/types.h>#include <sys/socket.h>#include <stdlib.h>#include <arpa/inet.h>#include <netinet/in.h>#include <unistd.h>#include <string.h>//./tcp_server 192.168.x.x 8080static void usage(const char* proc){ printf("usage:%s [server_ip] [server_port]\n",proc);}int startup(char* ip,int port){ int sock=socket(AF_INET,SOCK_STREAM,0); //创建套接字 if(sock<0) { perror("socket"); close(sock); exit(2); } struct sockaddr_in server; server.sin_family=AF_INET; server.sin_port=htons(port); server.sin_addr.s_addr=inet_addr(ip); if(bind(sock,(struct sockaddr*)&server,sizeof(server))<0) //绑定:填充网络 { perror("bind"); close(sock); exit(3); } if(listen(sock,10)<0) //监听 { perror("listen"); close(sock); exit(4); } return sock; //返回监听套接字 }void* request(void* arg){ int new_sock=(int)arg; while(1) { char buf[1024]; ssize_t s=read(new_sock,buf,sizeof(buf)-1); if(s>0) { buf[s]=0; printf("get new client# %s\n",buf); write(new_sock,buf,strlen(buf)); } else if(s==0) { printf("client close!!!\n"); break; } else { perror("read"); break; } } return (void*)0;}int main(int argc,char* argv[]){ if(argc != 3) //命令行用法 { usage(argv[0]); return 1; } int listen_sock=startup(argv[1],atoi(argv[2])); //创建监听套接字:函数三步 while(1) { struct sockaddr_in client; socklen_t addrlen=sizeof(client); int new_sock=accept(listen_sock,(struct sockaddr*)&client,&addrlen); //接收客户端信息进行通信 if(new_sock<0) { perror("accept"); continue; } //version 1.3 pthread_t id; pthread_create(&id,NULL,request,(void*)new_sock); //主线程监听接收客户端,创建线程为每一个客户端服务 pthread_detach(id); //使线程分离,主线程不用阻塞等待,操作系统去回收 //version 1.2 /*pid_t id=fork(); //即每有一个客户端连接则创建一个子进程为其服务 if(id<0) { perror("fork"); close(new_sock); } else if(id==0) //child 子进程进行处理请求,服务 { close(listen_sock); pid_t _id=fork(); //在子进程再次fork,使子进程的子进程去执行服务 if(_id>0) { exit(0); //子进程退出,即让父进程不会阻塞等待 } else if(_id==0) //child->child { while(1) { char buf[1024]; ssize_t s=read(new_sock,buf,sizeof(buf)-1); if(s>0) { buf[s]=0; printf("[%s:%d]# %s\n",inet_ntoa(client.sin_addr),ntohs(client.sin_port),buf); write(new_sock,buf,strlen(buf)); } else if(s==0) { printf("client close!!!\n"); break; } else { perror("read"); break; } } } close(new_sock); exit(0); } else //father 父进程进行监听接收多个客户端 { close(new_sock); waitpid(id,NULL,0); }*/ /*verison 1.1 //服务: printf("get new client [%s:%d]\n",inet_ntoa(client.sin_addr),ntohs(client.sin_port)); //接收成功 while(1) { char buf[1024]; //先从网络上读取客户端请求 ssize_t s=read(new_sock,buf,sizeof(buf)-1); if(s>0) { buf[s]=0; printf("client# %s\n",buf); //向客户端服务:写入网络 write(new_sock,buf,strlen(buf)); } else if(s==0) //若读取为0字节,则客户端关闭断开连接,则不在服务,再次去监听接收 { printf("client close!!!\n"); break; } else { perror("read"); break; } }*/ } return 0;}
tcp_client.c:
#include <stdio.h>#include <sys/types.h>#include <sys/socket.h>#include <stdlib.h>#include <arpa/inet.h>#include <netinet/in.h>#include <unistd.h>#include <string.h>//./tcp_client 192.168.x.x 8080static void usage(const char* proc){ printf("usage:%s [server_ip] [server_port]\n",proc);}int main(int argc,char* argv[]){ if(argc != 3) //命令行用法 { usage(argv[0]); return 1; } int sock=socket(AF_INET,SOCK_STREAM,0); //创建客户端套接字 if(sock<0) { perror("socket"); return 2; } struct sockaddr_in server; server.sin_family=AF_INET; server.sin_port=htons(atoi(argv[2])); server.sin_addr.s_addr=inet_addr(argv[1]); if(connect(sock,(struct sockaddr*)&server,sizeof(server))<0) //客户端与服务器建立连接 { perror("connect"); return 1; } //连接成功 char buf[1024]; while(1) { //先往网络上写 printf("Please Enter# "); fflush(stdout); ssize_t s=read(0,buf,sizeof(buf)-1); if(s>0) { buf[s-1]=0; write(sock,buf,strlen(buf)); } //从网络上读取服务器提供的信息 ssize_t _s=read(sock,buf,sizeof(buf)-1); if(_s>0) { buf[_s]=0; printf("server$ %s\n",buf); } } //关闭sock,则断开连接 close(sock); return 0;}
阅读全文
0 0
- 多进程多线程TCP服务器
- TCP服务器多线程 多进程简单测试
- 多线程、多进程TCP服务器比较
- 多线程、多进程TCP服务器、进程池和线程池
- 多进程多线程TCP服务器以及进程池
- 基于tcp的小型服务器(多线程多进程)
- 基于TCP的多进程和多线程服务器
- TCP server的实现,和多线程,多进程服务器
- 基于socket的Tcp多进程多线程服务器
- 【网络】实现简单的TCP、UDP服务器、TCP多进程/多线程服务器
- 多进程、多线程服务器
- 简单的网络服务器(简单的TCP,简单的UDP,多进程多线程TCP)
- tcp多进程并发服务器
- TCP多进程并发服务器
- Linux网络编程【三】:TCP服务器多进程和多线程(http访问)版本
- 实现多进程多线程服务器
- 多进程、多线程服务器程序
- socket--多进程,多线程服务器
- NAT的四种类型及检测[转]
- 数据库原理 、 SQL(DDL、DML)
- Hadoop中Yarnrunner里面submit Job以及AM生成 至Job处理过程源码解析
- An ffmpeg and SDL Tutorial 学习笔记(一)
- 一个有关sizeof的bug
- 多进程多线程TCP服务器
- EasyUI布局,窗口,口风琴,文件上传等
- Distributing Parts CodeForces
- 在控制台输出一个九九乘法表
- JAVA语言程序设计(基础篇)第十版
- 使用HttpURLConnection发请求获取数据
- 开源漏洞检测工具
- android-support-v4/v7/v13 介绍
- Chrome浏览器中使用Android sdk search在线查看源码