Linux C语言实现socket服务器和客户端

发布时间:2020-01-13
技术:Linux、C语言

概述

Demo在Linux系统中,用C语言实现socket服务器和客户端,实现过程涉及到的知识点有:tcp通信、socket通信和线程等。

详细

一、Socket通信:

1. 含义:

    Socket 是在应用层和传输层之间的一个抽象层,它把 TCP/IP 层复杂的操作抽象为几个简单的接口,供应用层调用实现进程在网络中的通信。


2. 通信流程:

1578548490739003451.jpg

3. Socket通信部分接口说明:

1. socket()
	功  能:创建套接字
	原  型:int socket(int domain, int type, int protocol);
	参  数:
			domain:协议族,通常为AF_INET,表示TCP/IP协议
			type:socket类型,如:SOCK_STREAM(指TCP)和SOCK_DGRAM(指UDP)等等
			protocol:套接口所用的协议,一般为0
	返回值:
			成功:socket文件描述符
			失败:-1,并设置errno
			
2. bind()
	功  能:将套接字和指定的端口相连
	原  型:int bind(int sock_fd, struct sockaddr_in *my_addr, int addrlen);
	参  数:
			sock_fd:socket文件描述符
			my_addr:设置服务器信息的sockaddr_in结构体指针
			addrlen:sockaddr_in结构体的长度
	返回值:
			成功:0
			失败:-1,并设置errno
	说  明:
			struct sockaddr_in{
  			short int sin_family;			//网络通信网络层协议  AF_INET
  			unsigned short int sin_port;	//端口
  			struct in_addr sin_addr;		//IP地址
  			unsigned char sin_zero[8];		//让sockaddr与sockaddr_in两个数据结构保持大小相同而保留的空字节
  		};

3. connect()
	功  能:连接服务器请求(客户端使用)
	原  型:int connect(int sock_fd, struct sockaddr *serv_addr,int addrlen);
	参  数:
			sock_fd:socket文件描述符
			serv_addr:包含远端主机IP地址和端口号的指针
			addrlen:sockaddr_in结构体的长度
	返回值:
			成功:0
			失败:-1,并设置errno

4. listen()
	功  能:创建一个套接口并监听申请的连接
	原  型:int listen(int sock_fd, int backlog);
	参  数:
			sock_fd:socket文件描述符
			backlog:请求队列中允许的最大请求数
	返回值:
			成功:0
			失败:-1,并设置errno

5. accecpt()
	功  能:接受客户端的服务请求
	原  型:int accept(int sock_fd, struct sockadd_in* addr, int addrlen);
	参  数:
			sock_fd:被监听的socket文件描述符
			addr:包含客户端IP地址和端口号的指针
			addrlen:sockaddr_in结构体的长度
	返回值:
			成功:客户端套接字描述符
			失败:-1,并设置errno
	
6. write()
	功  能:写入数据到fd中
	原  型:ssize_t write(int fd,const void *buf,size_t nbytes);
	参  数:
			fd:socket文件描述符
			buf:字符串数据地址
			nbytes:字符串数据大小
	返回值:
			实际写入的字节数,小于0为写入错误
			

6、read()
	功  能:从fd中读取数据
	原  型:ssize_t read(int fd,void *buf,size_t nbyte)
	参  数:
			fd:socket文件描述符
			buf:字符串数据地址
			nbyte:字符串数据大小
	返回值:
			>0: 实际读取的大小
			=0:读到末尾了
			<0:读取错误

8、close()
	功  能:关闭套接字
	原  型:int close(sock_fd);
	参  数:
			sock_fd:要关闭的socket文件描述符
	返回值:
			成功:0
			失败:-1


二、线程部分接口说明:

注意:Linux系统中使用线程库,编译时要加-lpthread,例如:gcc server.c -o server -lpthread

1. pthread_create()
	功  能:创建线程
	原  型:int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
                          void *(*start_routine) (void *), void *arg);
	参  数:
			thread:线程的TID号,唯一的
			attr:线程的属性 
			start_routine:任务函数指针,指向的函数类型 : void *func(void *)  
			arg:传递给任务函数使用的参数  
	返回值:
			成功:0
			失败:错误编号

2. pthread_exit()
	功  能:终止调用它的线程并返回一个指向某个对象的指针(常与pthread_join()一起使用)
	原  型:void pthread_exit(void *retval);
	参  数:
			retval:线程的退出状态值 
	返回值:
			无

3. pthread_join()
	功  能:以阻塞的方式等待指定的线程结束
	原  型:int pthread_join(pthread_t thread, void **retval);
	参  数:
			thread:等待的线程的TID号
			retval:用户定义的指针,用来存储被等待线程的返回值
	返回值:
			成功:0
			失败:错误编号
			
4. pthread_cancel()
	功  能:线程的取消
	原  型:int pthread_cancel(pthread_t thread);
	参  数:
			thread:取消的线程的TID号
	返回值:
			成功:0
			失败:错误编号


三、部分代码

int main()
{
	//1.创建网络的通信对象
	socket_fd = socket(AF_INET,SOCK_STREAM,0);
	if(socket_fd < 0)
	{
		perror("socket error!");
		return -1;
	}
	
	//2.定义服务器注册的网络端口 和 网络 IP 结构体
	struct sockaddr_in server_addr,client_addr;
	int len = sizeof(client_addr);
	
	server_addr.sin_family = AF_INET;	//设置网络层协议
	server_addr.sin_port = htons(6666);	//设置端口号
	server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");	//设置IP地址
	
	//3.绑定服务器的IP地址
	int ret = bind(socket_fd,(struct sockaddr *)&server_addr,sizeof(server_addr));
	if(ret != 0)
	{
		perror("bind error!");
		return -1;
	}
	
	//4.把服务器socket,设置为监听模式
	ret = listen(socket_fd,5);
	if(ret != 0)
	{
		perror("listen error!");
		return -1;
	}
	
	printf("等待客户端的连接请求:\n");
	
	//5.接收客户端的连接请求
	client_fd = accept(socket_fd,(struct sockaddr *)&client_addr,&len);
	if(client_fd < 0)
	{
		perror("socket error!");
		return -1;
	}

	printf("ip:%s\n",inet_ntoa(client_addr.sin_addr));
	printf("port:%d\n",ntohs(client_addr.sin_port));
	
	//创建线程
	pthread_t tid;
    	pthread_create(&tid,NULL,sock_read,NULL);
    	pthread_detach(tid); //设置为分离属性
	
	//5.发送网络数据
	char buf[1024] = {0};
	while(1)
	{
		scanf("%s",buf);
		write(client_fd,buf,strlen(buf));
	}
	
	close(socket_fd);
	
	return 0;
}

    运行命令:./server和./client


四、实现效果

1578548746886020647.png1578548760788062232.png


五、总结

    后续跟新以下Demo:

1578548789355091657.jpg


六、项目结构图

项目结构图.jpg

本实例支付的费用只是购买源码的费用,如有疑问欢迎在文末留言交流,如需作者在线代码指导、定制等,在作者开启付费服务后,可以点击“购买服务”进行实时联系,请知悉,谢谢
手机上随时阅读、收藏该文章 ?请扫下方二维码