流程:
![](https://i-blog.csdnimg.cn/blog_migrate/a493d7f6fc86af16adab8f7d64525864.png)
服务器:
socket:创建一个用与链接的套接字(用于链接)
填充结构体:填充服务器的ip和端口
bind:绑定自己的ip地址和端口
listen:监听,将主动套接字转为被动套接字
accept:阻塞等待客户端链接,链接成功返回一个用于通信套接字
recv:接收消息
send:发送消息
close:关闭文件描述符
客户端:
socket:创建一个套接字
填充结构体:填充服务器的ip和端口
connect:阻塞等待链接服务器
recv/send:接收/发送消息
close:关闭
服务器端:
int main(int argc, char const *argv[])
{
if (argc != 2)
{
printf("please input:%s <port>\n", argv[0]);
return -1;
}
//1.创建套接字
int sockfd, acceptfd;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
{
perror("socket err");
return -1;
}
printf("sockfd=%d\n", sockfd);
//填充ipv4的通信结构体
struct sockaddr_in serveraddr, caddr;
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons(atoi(argv[1])); //将主机小端转换为网络大端
//serveraddr.sin_addr.s_addr = inet_addr(argv[1]); //将ip地址转为机器使用的32位无符号整数
//自动获取IP
//serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
//serveraddr.sin_addr.s_addr = INADDR_ANY;
serveraddr.sin_addr.s_addr = inet_addr("0.0.0.0");
//2.绑定套接字
if (bind(sockfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) < 0)
{
perror("bind err");
return -1;
}
printf("bind ok\n");
//3.监听套接字,将主动套接字转为被动套接字
if (listen(sockfd, 5) < 0)
{
perror("listen err");
return -1;
}
socklen_t len = sizeof(caddr);
//4.阻塞等待客户端连接,连接成功返回一个用于通信的文件描述符
//循环等待客户端
while (1)
{
acceptfd = accept(sockfd, (struct sockaddr *)&caddr, &len);
if (acceptfd < 0)
{
perror("accept err");
return -1;
}
printf("client:ip=%s port=%d\n", inet_ntoa(caddr.sin_addr), ntohs(caddr.sin_port));
char buf[128];
pid_t pid = fork();
if (pid < 0)
{
perror("fork err");
return -1;
}
else if (pid == 0)
{
int sendbyte;
while (1)
{
fgets(buf, sizeof(buf), stdin);
if (buf[strlen(buf) - 1] == '\n')
buf[strlen(buf) - 1] = '\0';
sendbyte = send(acceptfd, buf, sizeof(buf), 0);
if (sendbyte < 0)
{
perror("send err");
return -1;
}
}
}
//5.循环接收消息 通信
else
{
int recvbyte;
while (1)
{
recvbyte = recv(acceptfd, buf, sizeof(buf), 0);
if (recvbyte < 0)
{
perror("recv err");
return -1;
}
else if (recvbyte == 0)
{
printf("client exit\n");
kill(pid,SIGKILL);
wait(NULL);
break;
}
else
{
printf("buf:%s\n", buf);
}
}
close(acceptfd);
}
}
close(sockfd);
return 0;
}
客户端:
int main(int argc, char const *argv[])
{
if (argc != 3)
{
printf("please input %s <ip> <port>\n", argv[0]);
return -1;
}
//1.创建套接子
int sockfd;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
{
perror("socket error.");
return -1;
}
printf("sockfd=%d\n", sockfd);
//填充ipv4的通信结构体 服务器的ip和端口
struct sockaddr_in serveraddr;
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons(atoi(argv[2]));
serveraddr.sin_addr.s_addr = inet_addr(argv[1]);
//2.请求链接服务器
if (connect(sockfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) < 0)
{
perror("connect error.");
return -1;
}
//5.循环发送消息 通信
char buf[128];
pid_t pid = fork();
if (pid < 0)
{
perror("fork err.");
return -1;
}
else if (pid == 0)
{
int recvbyte;
while (1)
{
recvbyte = recv(sockfd, buf, sizeof(buf), 0);
if (recvbyte < 0)
{
perror("recv err.");
return -1;
}
printf("buf:%s\n", buf);
}
}
else
{
int sendbyte;
while (1)
{
fgets(buf, sizeof(buf), stdin);
if (buf[strlen(buf) - 1] == '\n')
buf[strlen(buf) - 1] = '\0';
sendbyte = send(sockfd, buf, sizeof(buf), 0);
if (sendbyte < 0)
{
perror("send error.");
return -1;
}
if (strncmp(buf, "quit", 4) == 0)
{
kill(pid, SIGKILL);
wait(NULL);
exit(-1);
}
}
}
close(sockfd);
return 0;
}
运行结果显示:
![](https://i-blog.csdnimg.cn/blog_migrate/c78dc96eb67fb20548e173de90fdae55.png)