TCP/UDP客户端服务器实现通信

TCP/UDP实现编程
TCP服务器与客户端的连接过程:

客户端与服务器三次握手是在accept和connect之后建立的。
三次握手的过程:
A-->B 发送SYN
B->A 确认发一个ACK,再发一个SYN
A->B 确认发一个ACK


四次挥手过程:
A---->B  FIN
B----->A  ACK
( 注意:此时, A--->B 的通道被关闭, A 无法再向 B 发数据,但是 B--->A 的通道仍然还开着, B A 的剩下的数据发完之后, B 才会主动发出分手的 FIN 信号 )
B----->A   FIN
A----->B   ACK

为什么服务器在分手时需要等待2MSL才真正分手?
答:因为ACK发给对方,需要一个MSL时间,如果对方在这个时间内存收不到ACK会重发一个FIN信号给我,这个信号也要一个MSL时间。这样,如果经过两个MSL时间之后,A收不到任何信号,则可以得出结论:B已经收到了我最后的那个ACK了。

TCP服务器与客户端连接的代码实现:
//tcpserver.c
#include <stdio.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>

#include <netdb.h>
#include <unistd.h>
#include <sys/file.h>
#include <sys/mman.h>
#include <sys/wait.h>
#include <mqueue.h> //消息队列
#include <signal.h>
#include <semaphore.h>
#include <sys/socket.h>  //套接字接口
#include <arpa/inet.h>   //网络地址的转换
#include <time.h>

void formattime(char buffer[]){

	time_t ticks;
	ticks=time(NULL);
	snprintf(buffer,sizeof(char)*1024,"%.24s\n",ctime(&ticks));
}

int main(int argc, char const *argv[])
{
	int sockd=socket(AF_INET,SOCK_STREAM,0);

	struct sockaddr_in sockin;
	bzero(&sockin,sizeof(sockin));
	sockin.sin_family=AF_INET;
	sockin.sin_addr.s_addr=INADDR_ANY;//避免出现两块网卡出现问题
	sockin.sin_port=htons(2017);//两个字节
	if(bind(sockd,(struct sockaddr*)&sockin,sizeof(sockin))<0){
		perror("bind");
		exit(EXIT_FAILURE);
	}
	if(listen(sockd,10)<0){//最多接收十个客户端的连接
		perror("listen");
		exit(EXIT_FAILURE);
	}
	while(1){
		struct sockaddr_in clientaddr;//用来保存客户端的网络地址
		socklen_t clientlen=sizeof(clientaddr);//客户端网络地址的长度
		int fd = accept(sockd,(struct sockaddr*)&clientaddr,&clientlen);
		if(fd < 0){
			perror("accept");
			exit(EXIT_FAILURE);
		}
		char clientip[20];
		inet_ntop(AF_INET,&clientaddr.sin_addr,clientip,sizeof(clientip));
		printf("客户端%s(%d)已连接.\n",clientip,(ntohs)(clientaddr.sin_port));
		char buffer[1024];
		formattime(buffer);
		write(fd,buffer,strlen(buffer));
		close(fd);
	}
	return 0;
}

//tcpclient.c
#include <stdio.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>

#include <netdb.h>
#include <unistd.h>
#include <sys/file.h>
#include <sys/mman.h>
#include <sys/wait.h>
#include <mqueue.h> //消息队列
#include <signal.h>
#include <semaphore.h>
#include <sys/socket.h>  //套接字接口
#include <arpa/inet.h>   //网络地址的转换
#include <time.h>

//argv[1]是IP地址,argv[2]是端口
int main(int argc, char const *argv[])
{
	if(argc<3){
		printf("usage:filename ipaddress port");
		return -1;
	}
	//创建套接字
	int sockfd=socket(AF_INET,SOCK_STREAM,0);
	//绑定网络地址
	struct sockaddr_in sockin;
	sockin.sin_family=AF_INET;
	inet_pton(AF_INET,argv[1],&sockin.sin_addr);//将十进制的转换成二进制的形式,不需要长度
	sockin.sin_port=htons(atoi(argv[2]));
	//连接服务器
	int fd;
	fd = connect(sockfd,(struct sockaddr*)&sockin,sizeof(sockin));
	if(fd<0){
		perror("connect");
		exit(-1);

	}

	//读取信息
	char buffer[1024]={0};

	if(read(sockfd,buffer,sizeof(buffer))<0){

		perror("read");
		exit(-1);
	}

	write(1,buffer,strlen(buffer));
	close(fd);

	

	return 0;
}
UDP服务器与客户端的连接过程:

UDP服务器与客户端通信代码:

//udpserver.c
#include <stdio.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#include <netdb.h>
#include <unistd.h>
#include <sys/file.h>
#include <sys/mman.h>
#include <sys/wait.h>
#include <mqueue.h> //消息队列
#include <signal.h>
#include <semaphore.h>
#include <sys/socket.h>  //套接字接口
#include <arpa/inet.h>   //网络地址的转换
#include <time.h>

int main(int argc, char const *argv[])
{
	//创建socket
	int sockfd=socket(AF_INET,SOCK_DGRAM,0);
	//bind
	struct sockaddr_in sockin;
	sockin.sin_family=AF_INET;
	sockin.sin_addr.s_addr=INADDR_ANY;//接收任何网卡的输入,实际为0
	sockin.sin_port=htons(2020);
	if(bind(sockfd,(struct sockaddr*)&sockin,sizeof(sockin))<0){
		perror("bind");
		exit(-1);
	}
	//从客户端读取信息
	char buffer[1024]={0};
	struct sockaddr_in clientaddr;
	socklen_t len=sizeof(clientaddr);

	while(1){
		recvfrom(sockfd,buffer,sizeof(buffer),0,(struct sockaddr*)&clientaddr,&len);

		//写回到客户端
		sendto(sockfd,buffer,strlen(buffer),0,(struct sockaddr*)&clientaddr,sizeof(clientaddr));
	}
	close(sockfd);

	
	return 0;
}
//udpclient.c
#include <stdio.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>

#include <netdb.h>
#include <unistd.h>
#include <sys/file.h>
#include <sys/mman.h>
#include <sys/wait.h>
#include <mqueue.h> //消息队列
#include <signal.h>
#include <semaphore.h>
#include <sys/socket.h>  //套接字接口
#include <arpa/inet.h>   //网络地址的转换
#include <time.h>
//argv[1]是服务器ip地址 argv[2]端口号
int main(int argc, char const *argv[])
{
	//创建socket
	int sockfd=socket(AF_INET,SOCK_DGRAM,0);
	struct sockaddr_in serveraddr;
	serveraddr.sin_family=AF_INET;
	inet_pton(AF_INET,argv[1],&serveraddr.sin_addr);
	serveraddr.sin_port=htons(2020);
	//从客户端读取信息
	char buffer[1024]={0};
	gets(buffer);
	sendto(sockfd,buffer,strlen(buffer),0,(struct sockaddr*)&serveraddr,sizeof(serveraddr));

	bzero(buffer,sizeof(buffer));
	socklen_t len=sizeof(serveraddr);
	recvfrom(sockfd,buffer,sizeof(buffer),0,(struct sockaddr*)&serveraddr,&len);

	//将读出的数据写到屏幕上
	printf("返回来的数据是:\n");
	write(1,buffer,strlen(buffer));
	close(sockfd);

	
	return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值