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;//IPv4
server.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;//将信号处理函数的句柄赋值给handler
sigemptyset(&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=4
IP:192.168.1.10,port:60044
Bytes:1
i love you.
Bytes:1
process_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;
}
//结构体中成员变量初始化为0
bzero(&servaddr,sizeof(servaddr));
//初始化成员变量
servaddr.sin_family = AF_INET;//IPv4
servaddr.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;
}