send函数: 发送数据
原函数:ssize_t send(int sockfd, const void *buf, size_t len, int flags);
参数:sockfd,是由socket函数返回的套接字描述符
buf,要发送的数据
len,要发送的数据的大小
flags,一个标志位
recv函数: 接收数据
原函数:ssize_t recv(int sockfd, void *buf, size_t len, int flags);
参数:sockfd,由socket函数返回的套接字描述符
buf,接收数据的存储位置
len,接收的字节数
flags,一个标志位
flags | 说明 | recv | send |
---|---|---|---|
MSG_DONTROUTE | 不查路由表 | yes | |
MSG_DONTWAIT | 本操作不阻塞 | yes | yes |
MSG_OOB | 发送或接收带外数据 | yes | yes |
MSG_WAITALL | 查看外来消息 | yes | |
MSG_PEEK | 等待所有数据 | yes |
ps aux|grep server:查看server进程
#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/wait.h>#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <unistd.h>#include <fcntl.h>#include <signal.h>//最大连接数#define MAX_LISTEN_QUE 5//端口号#define SERV_PORT 8888//数组的最大字节数#define MAX_BUFFER_SIZE 100//创建套接字函数int mz_ipv4_tcp_create_socket(void){int listenfd, sockfd, opt = 1;struct sockaddr_in server, client;socklen_t len;int timep;int ret;//创建套接字listenfd = socket(AF_INET, SOCK_STREAM, 0);//IPv4,全双工通信if(listenfd < 0){perror(\"Create socket fail.\");return -1;}//设置地址的重用if((ret = setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt))) < 0){perror(\"Error, set socket reuse addr failed\");return -1;}//初始化清零操作bzero(&server, sizeof(server));server.sin_family = AF_INET;//IPv4server.sin_port = htons(SERV_PORT);//端口号server.sin_addr.s_addr = htonl(INADDR_ANY);//设置为所有都可连接//获得结构体地址长度len = sizeof(struct sockaddr);//套接字与服务器接口绑定if(bind(listenfd, (struct sockaddr *)&server, len)<0){perror(\"bind error.\");return -1;}//设置最大连接数listen(listenfd, MAX_LISTEN_QUE);//返回套接字return listenfd;}//数据处理函数int mz_process_data(int sockfd){int bytes;char buf[MAX_BUFFER_SIZE], read_buf[MAX_BUFFER_SIZE];//清空数组memset(buf, 0x00, MAX_BUFFER_SIZE);while(1){//清空数组memset(read_buf, 0x00, MAX_BUFFER_SIZE);//从通信套接字中接收数据,并存到read_buf中bytes = recv(sockfd, read_buf, 100, 0);if(bytes < 0){printf(\"read err.\\n\");return -1;}if(bytes == 0){printf(\"client connection closed.\\n\");return 0;}printf(\"Bytes:%lu\\n\", strlen(read_buf));//打印read_buf的长度//将读取到的内容发送到通信套接字中send(sockfd, read_buf, bytes, 0);//比较接收的数据是不是\'q\'if(!strcmp(read_buf, \"q\")){return 0;}//比较接收的数据是不是\'c\'if(!strcmp(read_buf, \"c\")){printf(\"i love you.\\n\");sprintf(read_buf, \"%s\",\"i love you.\\n\" );send(sockfd, read_buf, 12, 0);}}//关闭通信套接字close(sockfd);return 0;}//信号处理函数int mz_process_signal(int signo){//判断信号的类型switch(signo){case SIGCHLD:printf(\"process_signal\\n\");while(waitpid(-1, NULL, WNOHANG)>0);break;}}//创建信号处理的句柄int mz_set_signal_handler(void){struct sigaction act, oact;act.sa_handler = (void *)mz_process_signal;//将信号处理函数的句柄赋值给handlersigemptyset(&act.sa_mask);//清空信号集act.sa_flags = 0;act.sa_flags |= SA_RESTART;//定义要处理的信号和处理方法if(sigaction(SIGCHLD, &act, &oact) < 0){return -1;}return 0;}int main(int argc, char *argv[]){int listenfd, sockfd;struct sockaddr_in server, client;socklen_t len;int bytes =0 ;//调用创建信号句柄函数mz_set_signal_handler();len = sizeof(struct sockaddr);//调用套接字处理函数listenfd = mz_ipv4_tcp_create_socket();while(1){//服务器等待客户端连接sockfd = accept(listenfd, (struct sockaddr *)&client, &len);if(sockfd < 0){perror(\"accept error.\");return -1;}printf(\"sockfd=%d\\n\", sockfd);//打印客户端地址和端口号printf(\"IP:%s,port:%d\\n\",inet_ntoa(client.sin_addr),ntohs (client.sin_port));//创建子进程if(fork() == 0){//关闭套接字close(listenfd);//调用数据处理函数mz_process_data(sockfd);exit(0);}//关闭通信套接字close(sockfd);}return 0;}
运行结果
sockfd=4IP:192.168.1.10,port:60044Bytes:1i love you.Bytes:1process_signal
window系统下按win+r,进入cmd,输入telent 192.168.1.12 8888(telnet+IP地址+端口号)进行连接。输入c(通信)或者q(退出)
client
#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <unistd.h>#include <fcntl.h>#include <arpa/inet.h>int main(int argc,char *argv[]){int sockfd;struct sockaddr_in servaddr;char buf[100],read_buf[100];//存储读取的内容int bytes;//存储读取的字节数if((sockfd = socket(AF_INET,SOCK_STREAM,0)) < 0)//创建套接字{printf(\"socket error\\n\");return -1;}//结构体中成员变量初始化为0bzero(&servaddr,sizeof(servaddr));//初始化成员变量servaddr.sin_family = AF_INET;//IPv4servaddr.sin_addr.s_addr = inet_addr(\"192.168.1.12\");//转换为地址格式servaddr.sin_port = htons(8888);//主机序转换到网络序//连接服务器if(connect(sockfd,(struct sockaddr *)&servaddr,sizeof(servaddr)) < 0)//绑定服务器ip和端口到>套结字{perror(\"connect error\");return -2;}while(1){fgets(buf, 100, stdin);send(sockfd,buf,strlen(buf),0);//存储读取的数据和读取的字节数bytes = recv(sockfd,read_buf,100,0);if(bytes < 0){printf(\"Error ,read failed\\n\");close(sockfd);return -3;}//如果读取的字节数为0 ,就说明连接已经关闭了if(0 == bytes){printf(\"Server close connection\\n\");close(sockfd);return -4;}//打印读取的字节数和读取的内容printf(\"read bytes %d\\n\",bytes);printf(\"read_buf: %s\\n\",read_buf);}//关闭套结字close(sockfd);return 0;}