实现数据的回射功能,服务器端接收到客户端发送来的数据时会将同样数据发送回去,客户端之间没有数据通信
服务器端代码
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <pthread.h>
#define LISTEN_NUM 10 //最大允许连接数
/**
回射函数的处理,当收到客户单发送来的数据时将同样数据发送回去
**/
void* process(void *arg) {
char buf[1024] = {0};
int conn_fd = *(int*)arg;
int ret;
while((ret = read(conn_fd, buf, sizeof(buf))) > 0) {
if(ret > 0) {
write(conn_fd, buf, strlen(buf));
memset(buf, 0, sizeof(buf));
} else if(ret == 0) {
printf("the clint has closed\n");
conn_fd = 0;
close(conn_fd);
return NULL;
} else {
printf("error ret = %d", ret);
return NULL;
}
}
}
/**
启动服务器并进行侦听,基本套路
**/
int serve_tcp_start(const int port) {
int sockID;
sockID = socket(AF_INET, SOCK_STREAM, 0);
if(sockID < 0) {
perror("socket");
return -1;
}
struct sockaddr_in serName;
memset(&serName, 0, sizeof(serName));
serName.sin_port = htons(port);
serName.sin_family = AF_INET;
serName.sin_addr.s_addr = htonl(INADDR_ANY);
if(bind(sockID, (struct sockaddr*)&serName, sizeof(serName)) < 0) {
perror("bind");
return -1;
}
if(listen(sockID, LISTEN_NUM) < 0) {
perror("listen");
return -1;
}
return sockID;
}
/**
判断哪个套接口可用
**/
int get_conn_fd(int *fd) {
int i;
for(i=0; i<LISTEN_NUM; i++) {
if(*(fd+i) == 0) return i;
}
return -1;
}
int main() {
/*declare variables*/
int sock_fd;
int port = 8086;
int pos = 0;
int conn_fd[LISTEN_NUM] = {0};
pthread_t pid[LISTEN_NUM];
sock_fd = serve_tcp_start(port); //启动服务器
if(sock_fd < 0) {
perror("serve_tct_start\n");
return 0;
}
int tempConn;
while(1) {
tempConn = accept(sock_fd, NULL, NULL); //accept一直保持一个阻塞状态,当一个连接请求到达,会分配一个用于通信的描述符
pos = get_conn_fd(conn_fd); //找出一个可用的通信描述符
if(pos == -1) {
printf("no varibale socket for connect\n"); //如果没有可用就把连接丢弃了
} else {
conn_fd[pos] = tempConn;
pthread_create(&pid[pos], NULL, process, (void*)&conn_fd[pos]); //分配一个线程用于处理数据
}
}
return 0;
}
客户端代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
/**
获取客户端的socket
int port, char *ip 端口和ip地址
**/
int getClintSocket(int port, char *ip) {
int sockID;
sockID = socket(AF_INET, SOCK_STREAM, 0);
if(sockID == -1) {
perror("socket");
return 0;
}
struct sockaddr_in clint;
memset(&clint, 0, sizeof(clint));
clint.sin_port = htons(port);
clint.sin_family = AF_INET;
inet_pton(AF_INET, ip, &clint.sin_addr);
int flag = connect(sockID, (struct sockaddr*)&clint, sizeof(clint));
if(flag < 0) return -1;
return sockID;
}
int main() {
int port = 8086;
char *ip = "192.168.179.128";
int sock_fd = getClintSocket(port, ip); //得到套接字
if(sock_fd < 0) {
perror("connect");
return 0;
}
char buf[1024] = {0};
while(fgets(buf, sizeof(buf), stdin) != NULL) { //用fgets函数获取控制台的输入
if(strcmp(buf, "exit\n") == 0) { //判断得到的字符是否是exit,是就断开连接,fgets会记录回车'\n'
printf("close the socket and quit\n");
break;
} else {
write(sock_fd, buf, strlen(buf)-1); //向服务器端写数据,同时清空buf
memset(buf, 0, sizeof(buf));
read(sock_fd, buf, sizeof(buf)); //从服务器端得到数据,打印到控制台
printf("recv the message:%s\n", buf);
}
}
printf("socket is close\n");
close(sock_fd);
return 0;
}
结果