TCP回射1-----线程

实现数据的回射功能,服务器端接收到客户端发送来的数据时会将同样数据发送回去,客户端之间没有数据通信


服务器端代码

#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;
}
结果


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值