2021-11-07

网络编程TCP客户端和服务端

一、线程方式实现聊天TCP

1.1 Client

#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>
//定义互斥锁
pthread_mutex_t m;

void *recvfunc(void *arg)
{
usleep(50);
int sockfd =*(int *)arg;
while(1)
{	//加锁
	pthread_mutex_lock(&m);
	//接受服务器内容
	char recvMsg[50]={0};
	recv(socked, recvMsg,50,0);
	printf("客户端接受的内容:%s", recvMsg);

//解锁
	pthread_mutex_unlock(&m);
	usleep(50);
	}
}
int main(int argc, char *argv)
{
	if(argc!=3)
	{
		printf("请输入ip 与 端口号\n");
		return -1;
	}
	int socketfd = socket(AF_INET,SOCK_STREAM,0);
	if(socketfd == -1)
	{
		perror("socket faile");
		return -1;
	}
	struct sockaddr_in serAddr;
	socklen_t len = sizeof(serAddr);
	bzero(&serAddr, sizeof(serAddr));  //清空
	serAddr.sin_family = AF_INET;  //设置ip4
	
	serAddr.sin_port=htonl(atoi(argv[1]));   /设置端口,外部输入,atoi转化为整形,跳过空格)
	serAddr.sin_addr.s_addr = inet_addr(argv[1]);// 将ip设置为网络模式(确定和哪一个主机进行通信)
	
	// 2.连接服务器,默认阻塞
	int ret = connect(socketfd, (struct sockaddr *)&serAddr,len);
	if(ret == -1)
	{
		perror("connect failed");
		return -1;
	}
	
	//互斥锁初始化
	pthread_mutex_init(&m,NULL);
	//创建线程
	pthread_t tid;
	pthread_create(&tid,NULL,recvfunc,(void*)socketfd);
	while(1)
	{
		//加锁
		pthread_mutex_lock(&m);
		//6.发送信息
		char sendMsg[50] = {0};
		printf("请客户端输入内容: ");
		fgets(sendMsg,50,stdin);
		send(socketfd, sendMsg, 50, 0);
		if(!strncmp(sendMsg,"quit",4))
		{
			pthread_mutex_unlock(&m); //解锁走人
			//7.关闭套接字
			close(socketfd);
			exit(0);
		}
		
		pthread_mutex_unlock(&m);  //解锁
		usleep(50);	
	}
	
	return 0;
}


1.2 server

#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>
#include <stdbool.h>
//------------------------------
pthread_mutex_t m;  //定义互斥锁变量
//------------------------------
void *recvfunc(void *arg)
{
	
	int connectfd = *((int *)arg);  //服务器通过connctfd收发数据
	while(1)
	{
		pthread_mutex_lock(&m);
		//6.接收信息
		char recvMsg[50] = {0};
		recv(connectfd, recvMsg, 50, 0);
		printf("服务器接收的内容 : %s",recvMsg);
		if(!strncmp(recvMsg,"quit",4))
		{
			//解锁走人
			pthread_mutex_unlock(&m);
			//7.关闭套接字
			close(connectfd);
			exit(0);
		}
			
		pthread_mutex_unlock(&m);
		usleep(50);
	}
}
//------------------------------
bool init_tcp(int *socketfd,int port,socklen_t *len)
{
	//1.创建套接字(买手机)
	*socketfd = socket(AF_INET, SOCK_STREAM, 0);
	if(*socketfd == -1)
	{
		perror("socket faile");
		return false;
	}
	//2.设置服务器ip和端口号(设置手机卡)
	struct sockaddr_in serAddr;
	*len = sizeof(serAddr); // 获取结构体大小
	bzero(&serAddr,sizeof(serAddr));
	serAddr.sin_family = AF_INET; // 设置ipv4 
	serAddr.sin_port = htons(port); // 将端口号(确定主机的哪个进程通信)转为大端模式
	//serAddr.sin_addr.s_addr = inet_addr(argv[1]);// 将ip设置为网络模式(确定和哪一个主机进行通信)
	// 自动获取ip	/usr/include/linux/in.h 275
	serAddr.sin_addr.s_addr = htonl(INADDR_ANY);
		
	//3.绑定手机,绑定的是服务器(rose)自己的ip和端口号
	int ret = bind(*socketfd,(struct sockaddr *)&serAddr,*len);	
	if(ret == -1)
	{
		perror("bind faile");
		return false;
	}
			
	//4.监听(设置来电显示)	
	ret = listen(*socketfd,5);
	if(ret == -1)
	{
		perror("listen faile");
		return false;
	}
	
	return true;
}
//------------------------------
int main(int argc,char **argv)
{
	if(argc != 2)
	{
		printf("请输入端口号\n");
		return -1;
	}
	
	int port = atoi(argv[1]);
	socklen_t len;
	int socketfd;
	// 初始化tcp
	bool ret = init_tcp(&socketfd,port,&len);
	if(ret == false)
	{
		return -1;
	}
	//5.等待连接(电话)
	// 保存客户端的ip和端口号
	struct sockaddr_in clientAddr;
	int connectfd = accept(socketfd, (struct sockaddr *)&clientAddr, &len);
	char *clientIP = inet_ntoa(clientAddr.sin_addr);
	printf("client ip = %s\n",clientIP);
	
	// 初始化互斥锁
	pthread_mutex_init(&m,NULL);
	
	// 创建线程
	pthread_t tid;
	pthread_create(&tid,NULL,recvfunc,(void *)&connectfd);
	usleep(50);
	while(1)
	{
		pthread_mutex_lock(&m);
		// 给客户端发送内容
		printf("请客户端输入内容: ");
		char sendMsg[50] = {0};
		fgets(sendMsg,50,stdin);
		send(connectfd, sendMsg, 50, 0);
		if(!strncmp(sendMsg,"quit",4))
		{
			pthread_mutex_unlock(&m);
			//7.关闭套接字
			close(connectfd);
			exit(0);
		}
		pthread_mutex_unlock(&m);	
		usleep(50);			
	}
	
	//7.关闭套接字
	close(socketfd);
	close(connectfd);
	
	return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Qt历险记

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值