思想:
主进程专门用于连接多个客户端的请求,若有一条客户端连接进来,主进程就创建一个子进程,用该子进程来处理客户端的业务数据。
tcp_server.c
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <string.h>
#include <netinet/in.h>//sockaddr_in
#include <unistd.h>
#include <arpa/inet.h> // 包含 inet_addr 函数的声明
#include <pthread.h>
#define BUF_SIZE 20
void *ThreadFunc(void *arg)
{
int iClient = *(int *)arg;
char buf[BUF_SIZE] = {0};
int ret = -1;
while(1){
ret = recv(iClient, buf, BUF_SIZE, 0);
if(ret <= 0){
printf("recv error!\r\n");
close(iClient);
pthread_exit("thread exit");
}
printf("server recv data:%s\r\n",buf);
//send
send(iClient, buf, BUF_SIZE, 0);
}
}
int main(int argc, const char *argv[])
{
//1.socket
int iServer = socket(AF_INET, SOCK_STREAM, 0);
if(-1 == iServer){
puts("----------1、create socket error!----------");
return -1;
}
puts("----------1、create socket ok!----------");
//2.bind
struct sockaddr_in stServer;
stServer.sin_family = AF_INET;//第一个成员
stServer.sin_port = htons(8888);//第二个成员
stServer.sin_addr.s_addr = inet_addr("127.0.0.1");//将点分十进制ip地址转换为32位无符号整数
int ret = bind(iServer, (struct sockaddr *)&stServer, sizeof(struct sockaddr));
if(-1 == ret){
puts("----------2、bind error!----------");
return -1;
}
puts("----------2、bind ok!----------");
//3.listen
ret = listen(iServer, 5);
if(-1 == ret){
puts("----------3、listen error!----------");
return -1;
}
puts("----------3、listen ok!----------");
//4.accept
//函数原型:int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
//函数作用:接收客户端的连接请求
//参数1:文件描述符 ---> socket的返回值
//参数2:指向存放对方主机信息结构体的指针
//参数3:指向struct sockaddr大小的指针
//返回值:成功返回 新的文件描述符 ---> 标识一个新的网络软通道 --->
//用做收发正文数据(recv/send), 失败 -1
struct sockaddr_in stClient;//存放对方的主机信息
socklen_t len = sizeof(struct sockaddr_in);
char buf[BUF_SIZE] = {0};
while(1){
memset(buf, 0, BUF_SIZE);
int iClient = accept(iServer, (struct sockaddr *)&stClient, &len);
if(-1 == iClient){
continue;//当前客户端出错转向下一个客户端
}
printf("----------4、accept ok! iClient = %d\r\n----------",iClient );//标准输入输出出错,所以下一个打开的文件一定是4
// \r\n适用于所有操作系统,此考虑系统移植
//thread
pthread_t tID = -1;
if(0 != pthread_create(&tID, NULL, ThreadFunc, &iClient)){
perror("create thread error");
close(iClient);
continue;
}
printf("create thread ok! iClient:%d\r\n",iClient);
}
return 0;
}
tcp_client.c
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#define BUF_SIZE 20
//main函数参数,如果需要键入IP则给定即可
int main(int argc, const char *argv[])
{
//1、socket
int iClient = socket(AF_INET, SOCK_STREAM, 0);
if(-1 == iClient){
puts("----------1、create socket error!");
return -1;
}
puts("----------1、create socket ok!");
//2、connect
struct sockaddr_in stServer;
stServer.sin_family = AF_INET;
stServer.sin_port = htons(8888);
//stServer.sin_addr.s_addr = inet_addr("192.168.15.71");
stServer.sin_addr.s_addr = inet_addr("127.0.0.1");
int ret = connect(iClient, (struct sockaddr *)&stServer, sizeof(struct sockaddr_in));
if(-1 == ret){
puts("----------2、connect error!");
return -1;
}
puts("----------2、connect ok!");
char buf[BUF_SIZE] = {0};
while(1){
//gets();
//char *fgets(char *s, int size, FILE *stream);
fgets(buf, BUF_SIZE, stdin);//更安全,边界检查
//3、send recv
ret = send(iClient, buf, BUF_SIZE, 0);
if(-1 == ret){
puts("----------3、send data error!");
}
printf("----------3、send data ok! buf = %s\r\n",buf);
//recv
//函数原型:ssize_t recv(int sockfd, void *buf, size_t len, int flags);
memset(buf, 0, BUF_SIZE);
ret = recv(iClient, buf, BUF_SIZE, 0);
if(-1 == ret){
puts("----------4、recv error!");
return -1;
}
printf("----------4、recv data ok! buf = %s\r\n",buf);
}
//close(iClient);
return 0;
}