linux下实现服务器与客户端(连接时给客户端发送时间)
来源:互联网 发布:昆仑虚麒麟臂升阶数据 编辑:程序博客网 时间:2024/05/19 11:50
OSI七层模型
应用层,表达层,会话层,传输层,网络层,数据链路层,物理层
(顺口溜式记忆:应用表示会话层,传输网络链路层,还有一个物理层)
TCP/IP四层模型
应用层,传输层,互联网络层,网络接口层
实现一个服务器向连接的客户端发送系统时间
从命令行接受端口号
服务器中止时打印出结束信息
sockfd设为全局变量
sig_handler为终止信号运行函数
创建socket
int socket(int domain, int type, int protocol);
应用层:面向用户
传输层:如TCP,UDP
网络层:如IP
socket位于应用层与传输层之间
返回值:套接字描述符(一切皆文件)
domain:协议族(family)决定地址类型如:AF_INET
type:socket类型如:SOCK_STREAM,SOCK_DGRAM
protocol:指定协议如:IPPROTO_TCP、IPPTOTO_UDP
或者填0会根据type选择对应的
这个套接字用于监听
socket结构体如下:
绑定socket结构体bind
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
把地址族的特定地址给socket,不调用会随机分配端口号
返回值:成功返回0
sockfd:套接字描述符
addr:套接字协议地址
addr:地址大小
监听listen
int listen(int sockfd, int backlog);
返回值:成功返回0
sockfd:套接字描述符
backlog:队列最大连接数
接受客户端请求accept
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
返回值:一个新的连接客户端的描述符(区别于前面监听用的)
sockfd:监听用套接字
addr:客户端的地址信息,不需要可设为NULL
addrlen:地址长度,同样可为NULL
调用系统IO通信
通过write给客户端发送服务器当前时间
右边终端:编译-运行-终止
服务器源码:
#include <stdio.h>#include <stdlib.h>#include <memory.h>#include <signal.h>#include <time.h>#include <sys/socket.h>#include <errno.h>#include <netdb.h>#include <unistd.h>#include <string.h>#include <pthread.h>#include <arpa/inet.h>int sockfd;void sig_handler(int signo){ if(signo == SIGINT) { printf("server close\n"); close(sockfd); exit(1); }}/*输出连接的客户端的信息*/void out_addr(struct sockaddr_in *clientaddr){ //网序转主机序 int port = ntohs(clientaddr->sin_port); char ip[16]; memset(ip,0,sizeof(ip)); inet_ntop(AF_INET, &clientaddr->sin_addr.s_addr,ip,sizeof(ip)); printf("client:%s(%d) connected\n",ip,port);}void do_service(int fd){ long t = time(0); char *s = ctime(&t); size_t size = strlen(s) * sizeof(char); if(write(fd,s,size) != size) { perror("write error"); }}int main(int argc,char *argv[]){ if(argc < 2) { printf("usage:%s #port\n",argv[0]); exit(1); } if(signal(SIGINT,sig_handler) == SIG_ERR) { perror("signal sigint error"); exit(1); } /*创建socket *socket为结构体 *AF_INET: IPV4 *SOCKET_STREAM:tcp协议 */ sockfd = socket(AF_INET,SOCK_STREAM,0); /* * socket跟地址绑定(ip/port) */ struct sockaddr_in serveraddr; memset(&serveraddr,0,sizeof(serveraddr)); /*填入ip,port,internet地址族*/ serveraddr.sin_family = AF_INET;//ipv4 serveraddr.sin_port = htons(atoi(argv[1]));//port /*可以绑定指定ip 如:serveraddr.sin_addr.s_addr = "192.168.1.10"; 或者用系统定义的宏 #define INADDR_ANY (uint32_t)0x00000000 可以响应所有接口的请求 */ serveraddr.sin_addr.s_addr = INADDR_ANY; if(bind(sockfd,(struct sockaddr*)&serveraddr, sizeof(serveraddr)) < 0) { perror("bind error"); exit(1); } /*监听指定端口 *接受来自服务器的请求 *将客户端请求放置对应队列 */ if(listen(sockfd,10) < 0)//10为队列长度 { perror("listen error"); exit(1); } /*调用accept从队列中获取一个客户端请求 *若没有链接会阻塞,直到有一个连接 */ struct sockaddr_in clientaddr; socklen_t clientaddr_len = sizeof(clientaddr); while(1) { int fd = accept(sockfd,(struct sockaddr*)&clientaddr, &clientaddr_len); if(fd < 0) { perror("accept error"); continue; } /*调用系统IO通信*/ out_addr(&clientaddr); do_service(fd); /*关闭套接字*/ close(fd); } return 0;}
实现客户端
从命令行接受ip和端口号 创建套接字
连接服务器connect
int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
对应于服务器listen
返回值:成功返回0失败-1
sockfd:客户端套接字描述符
addr:要连接的服务器地址
addrlen:地址长度
调用系统IO通信
read读取来自服务器的消息
客户端源代码:
#include <stdio.h>#include <stdlib.h>#include <netdb.h>#include <string.h>#include <memory.h>#include <sys/socket.h>#include <arpa/inet.h>#include <unistd.h>int main(int argc,char *argv[]){ if(argc < 3) { printf("usage:%s ip port\n",argv[0]); exit(1); } /*创建socket*/ int sockfd = socket(AF_INET,SOCK_STREAM,0); if(sockfd < 0) { perror("socket error"); exit(1); } struct sockaddr_in serveraddr; memset(&serveraddr,0,sizeof(serveraddr)); serveraddr.sin_family = AF_INET; serveraddr.sin_port = htons(atoi(argv[2])); inet_pton(AF_INET,argv[1],&serveraddr.sin_addr.s_addr); /*连接到服务器*/ if(connect(sockfd,(struct sockaddr*)&serveraddr, sizeof(serveraddr)) < 0) { perror("connect error"); exit(1); } /*系统IO通信*/ char buffer[1024]; memset(buffer,0,sizeof(buffer)); size_t size; if((size = read(sockfd,buffer,sizeof(buffer))) < 0) { perror("read error"); } if(write(1,buffer,size) != size) { perror("write error"); } /*关闭套接字*/ close(sockfd); return 0;}
编译运行服务器和客户端结果(左边服务器):
(服务器循环,每连接一个客户端就发送系统时间)
- linux下实现服务器与客户端(连接时给客户端发送时间)
- linux 下实现服务器与客户端连接小例子
- Android 使用Socket实现服务器与手机客户端的长连接三:clientA 发送给clientB,定点发送
- linux下实现服务器与客户端
- Linux下配置NTP时间服务器客户端
- linux 下 ssh客户端 连接远程服务器
- window下ssh客户端连接linux服务器:
- socket编程(Linux下使用select函数实现多客户端连接服务器)
- java实现代理服务器,接收客户端连接,发送到对应服务器
- Android简单实现Socket通信,客户端连接服务器后,服务器向客户端发送文字数据
- linux下多线程控制服务器与客户端
- Linux下Socket服务器与客户端编程
- linux下建立服务器与客户端
- Java客户端给服务器发送文件
- Linux下通过socket通信实现客户端向服务器发送文件
- Linux下网络socket编程——实现服务器(select)与多个客户端通信
- WCF 客户端与服务器时间不同步无法连接的解决方法
- 客户端将手机号发送给服务器,服务器将包含该手机号文件名发送给客户端
- 【职业生涯】读《内向者优势》有感
- JDK动态代理详解
- C++中的内存分配
- 一维码ITF 25简介及其解码实现(zxing-cpp)
- PAT 1099. Build A Binary Search Tree (30)
- linux下实现服务器与客户端(连接时给客户端发送时间)
- Java Lambda表达式初探
- [BZOJ3530][Sdoi2014]数数(AC自动机+数位dp)
- Nginx函数ngx_single_process_cycle学习笔记
- [牛客网]二叉树的镜像
- How does Linux detect your webcam?
- Java集合框架源码剖析:LinkedHashSet 和 LinkedHashMap
- 安装maven
- 支持优先队列操作的TreeSet