日常开发中,我们经常会遇到用Linux主机充当TCP服务器的情况,只要是带网口或者带WIFI的Linux系统,都可以充当TCP/UDP的服务器或者客户端。Liunx环境下进行TCP通信要比PC更为简单,因为在Linux的系统API中,就自带了TCP/UDP Socket通信的函数,而如果Windows要进行TCP/UDP通信,还要安装相应的软件库来启动,加载相关的开发环境(如QT、MFC等)。我这篇文章的针对人群是Linux和C语言基础非常浅显的小白,语言风格尽量通俗易懂,力求小白都可以看懂、理解。
TCP通信的上下级层次结构就不多赘述了,TCP属于OSI参考模型中的传输层,向上一级的应用层协议有HTTP、FTP等,这些协议都必须以以TCP Socket通信为基础的。TCP往下的网络层的协议是IP协议,TCP通信必须建立在IP层,IP层又是建立在数据链路层和物理层这些底层的硬件基础上。
接下来重点讲的是Linux TCP通信的流程。TCP服务器在一开始的时候必须要进行socket()、bind()、listen()、accept()的操作。socket()操作是建立TCP的收发套接字,套接字是通信的数据基础;bind()操作是将socket与TCP服务器绑定,这个操作主要跟TCP服务器开放的端口有关,当端口被占用时则bind()操作失败;listen()顾名思义,就是接听TCP客户端的连接请求;accept()则是接受TCP客户端的请求。accept()是阻塞操作,如果以我们常规的思维来理解,则accept()和listen()应该是同一个东西并且阻塞,因为我们很少会遇到TCP服务器拒绝TCP客户端连接请求的,但是程序是要求严谨的,listen()和accept()操作都必须有并且顺序不能随意改变。
操作建立之后,就是recv()接收((有些文章会把recv()写成read(),意义完全一样))和send()发送操作了(有些文章会把send()写成write(),意义完全一样),其中recv()是阻塞操作,因此Linux要实现TCP服务器的接收和发送一体,就必须使用多线程应用。在Linux中,多线程是真正的多线程(除了单核心单线程CPU),并不是时间片轮转调度,新开辟出来的一个线程,跟原有的线程是完全独立运行的,线程间通信必须要使用信号量、消息队列或者邮箱,在本次TCP通信中,由于TCP服务器要同时进行收发操作,且收发操作完全独立,最关键是接收操作还是阻塞的,那就必须启用多线程,详情看下面的代码。
首先是完成TCP服务器的准备工作,第一步是设定TCP服务器的工作模式(默认是AF_INET,无需深究,官方设定)、IP地址和端口:
struct sockaddr_in bindaddr; bindaddr.sin_family=AF_INET; bindaddr.sin_addr.s_addr=inet_addr(argv[1]); bindaddr.sin_port=htons(atoi(argv[2]));
int ret,fd_socket; fd_socket=socket(AF_INET,SOCK_STREAM,0); if(fd_socket==-1) { printf("套接字初始化失败!\n"); return -1; } ret=bind(fd_socket,(struct sockaddr *)&bindaddr,addrsize); if(ret==-1) { printf("套接字绑定失败!\n"); return -1; } ret=listen(fd_socket,5); if(ret==-1) { printf("服务器监听失败!\n"); return -1; } newsock=accept(fd_socket,(struct sockaddr *)&boyaddr,&addrsize);
pthread_t id1; pthread_create(&id1,NULL,Scanf_Thread,NULL);
int newsock; void *Scanf_Thread(void *arg) { int len; char *s; while(1) { bzero(s,0); scanf("%d",&len); s=(char *)malloc(len); scanf("%s",s); send(newsock,s,len,0); free(s); } } main函数的while(1)里面添加: while(1) { bzero(recvbuf,100); recv(newsock,recvbuf,100,0); printf("客户端发来数据:%s\n",recvbuf); }其中recvbuf是char字符串。这样,一个最简单的TCP服务器收发程序就搞定了,先来看看效果,运行程序,并输入IP 169.254.122.7,端口6666:
收发助手设置为TCP客户端模式,输入IP 169.254.122.7,端口6666,点击连接:
客户端向服务器发送多条数据:
服务器向客户端发送多条数据:
原创作品,未经权利人授权禁止转载。详情见转载须知。 举报文章
我要举报该内容理由
×