TCP 服务器与客户端
2015-08-25 23:53
489 查看
Linux下的TCP服务器与客户端编程都是分步骤来做的,这是一个并发的服务器
代码加注释服务器端:
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <sqlite3.h> #include <signal.h> #include <time.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> /** 并发服务器,来一个客户端创建一个进程为它服务 */ /* 定义一个结构体 */ typedef struct { int type; //接受客户请求码 简单设为 1表示返回字符串长度 2表示检查字符串是否有i char data[256]; // 接收客户的数据 } MSG; void do_client(int connfd); int main() { int connfd, listenfd;//定义连接文件描述符 与 监听描述符 pid_t pid;//定义进程描述符号 /*struct sockaddr_in则是internet环境下套接字的地址形式,是结构体 一般情况下,需要把sockaddr_in结构强制转换成sockaddr结构再传入系统调用函数中。*/ struct sockaddr_in myaddr; /**1、参数domain指明通信域,如PF_UNIX(unix域),PF_INET(IPv4), PF_INET6(IPv6)等 2、type指明通信类型,最常用的如SOCK_STREAM(面向连接可靠方式, 比如TCP)、SOCK_DGRAM(非面向连接的非可靠方式,比如UDP)等。 3、参数protocol指定需要使用的协议 */ if((listenfd = socket(PF_INET, SOCK_STREAM, 0)) < 0) { perror("fail to socket"); exit(-1); } bzero(&myaddr,sizeof(myaddr)); //清空数据 myaddr.sin_family = PF_INET; //套接字的网络地址 myaddr.sin_port = htons(atoi("8888"));//端口号 myaddr.sin_addr.s_addr = inet_addr("127.0.0.1");//ip地址 //绑定端口号与ip地址 把sockaddr_in结构强制转换成sockaddr结构 if(bind(listenfd,(struct sockaddr *)&myaddr,sizeof(myaddr)) < 0) { perror("fail to bind"); exit(-1); } //当用户太多时系统为我们保存5个连接等待 if (listen(listenfd, 5) < 0) { perror("fail to listen"); exit(-1); } printf("------------ Server is running --------\n"); //当客户段与服务器断开连接时,清理僵尸进程 signal(SIGCHLD, SIG_IGN); while ( 1 ) { //父进程负责与客户端连接,此方法是阻塞状态,一旦有客户端过来 //创建子进程,子进程负责与客户端交互 if ((connfd = accept(listenfd, NULL, NULL)) < 0) { perror("fail to accept"); exit(-1); } if ((pid = fork()) < 0) { perror("fail to fork"); exit(-1); } else if (pid == 0) { //子进程不需要监听,可以关闭 close(listenfd); do_client(connfd); } //父进程不需要连接,可以关闭 close(connfd); } return 0; } void do_client(int connfd) { MSG buf; int len; int i = 0; //将从客户端接收的数据保存在buf中 while (recv(connfd, &buf, sizeof(buf), 0) > 0) { switch ( buf.type ) { case 1 : len = strlen(buf.data);//计算长度 printf("客户端过来的数据是:%s 长度为:%d\n",buf.data,len); sprintf(buf.data,"%d",len);//将长度保存在这返回个客户端 send(connfd, &buf, sizeof(buf), 0);//将处理后的数据发送给客户端 break; case 2 : len = strlen(buf.data); for(i = 0; i < len; i++) { if(buf.data[i] == 'i') { buf.type = 0;//表示有 break; } } if(buf.type == 0) { printf("客户端过来的数据是:%s 有i\n",buf.data); bzero(buf.data,256); //strcpy(buf.data,"有 i"); sprintf(buf.data,"有 i",stdin); }else{ printf("客户端过来的数据是:%s 没有i\n",buf.data); bzero(buf.data,256); sprintf(buf.data,"没有 i",stdin); } send(connfd, &buf, sizeof(buf), 0); break; } } printf("\nclient quit\n"); exit(0); return; }
客户端
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <sqlite3.h> #include <signal.h> #include <time.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> /** 客户端 */ /* 定义一个结构体 */ typedef struct { int type; //给服务端发送请求码 char data[256]; // 接收服务器段的数据 } MSG; int main() { int connfd, listenfd;//定义连接文件描述符 与 监听描述符 /*struct sockaddr_in则是internet环境下套接字的地址形式,是结构体 一般情况下,需要把sockaddr_in结构强制转换成sockaddr结构再传入系统调用函数中。*/ struct sockaddr_in myaddr; /**1、参数domain指明通信域,如PF_UNIX(unix域),PF_INET(IPv4), PF_INET6(IPv6)等 2、type指明通信类型,最常用的如SOCK_STREAM(面向连接可靠方式, 比如TCP)、SOCK_DGRAM(非面向连接的非可靠方式,比如UDP)等。 3、参数protocol指定需要使用的协议 */ if((listenfd = socket(PF_INET, SOCK_STREAM, 0)) < 0) { perror("fail to socket"); exit(-1); } bzero(&myaddr,sizeof(myaddr)); //清空数据 myaddr.sin_family = PF_INET; //套接字的网络地址 myaddr.sin_port = htons(atoi("8888"));//服务器端口号 myaddr.sin_addr.s_addr = inet_addr("127.0.0.1");//服务器端ip地址 //绑定端口号与ip地址 把sockaddr_in结构强制转换成sockaddr结构 /* 客户程序发起连接请求 */ if(connect(listenfd,(struct sockaddr *)(&myaddr),sizeof(struct sockaddr))==-1) { perror("connect"); exit(1); } /* 连接成功了 */ printf("------------ Client is running --------\n"); MSG msg; while(1) { printf("\n输入1计算长度,输入2查找字符串是否有i,输入3表示退出:\n"); int type = 0; scanf("%d", &type); if(type == 3) break; msg.type = type; printf("输入内容:"); //fgets(msg.data,256,stdin); scanf("%s", msg.data); msg.data[strlen(msg.data)] = '\0'; send(listenfd, &msg, sizeof(MSG) ,0); //向服务器发送数据 recv(listenfd, &msg, sizeof(MSG), 0);;//等待服务器的数据 printf("------------ 结果为:%s --------\n", msg.data); } /* 结束通讯 */ close(listenfd); exit(0); return 0; }
最后贴上运行图:
服务器端:运行结果
客户端:运行结果
相关文章推荐
- Volley网络通信框架学习笔记(二)
- 网络
- BeautifulSoup
- TCP/IP协议详解-TCP简介与TCP建立与终止
- 发送HTTP请求
- TCP/IP协议
- (一二五)手机网络状态的监听
- (一二五)手机网络状态的监听
- 网络爬虫:URL去重策略之布隆过滤器(BloomFilter)的使用
- 网络爬虫:URL去重策略之布隆过滤器(BloomFilter)的使用
- TCP客户端和服务端的通信,通过服务端将客户端的小写字母转化成大写发送回来
- 在Ubuntu 14.04 64bit上使用网络诊断工具mtr
- Python源码分析1 - Building Python http://blog.csdn.net/atfield/article/details/1396729
- 2016网络红人萧天 最新资料
- 网络相关的Linux命令总结
- 计算机网络系统--常用DOS命令
- TCP CLOSE_WAIT 过多解决方案
- centos7无线网络连接
- Http 专题一:概述
- 计算机网络——计算机网络和因特网