Linux下C语言TCP编程02
来源:互联网 发布:vscode 支持xp吗 编辑:程序博客网 时间:2024/05/17 07:46
#include <stdio.h>#include <stdlib.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <sys/types.h> #include <string.h>#include <unistd.h>extern char **environ;int clientNum=0;char clientName[7]="client";int main(){int ret = 0; int addr_len;int portnum = 5555;//端口号char recvbuffer[1024];//接收数据缓冲区 int serversocket,clientsocket;//服务器调用socket()之后的描述符 struct sockaddr_in server_addr;//服务器套接字 struct sockaddr_in client_addr;//客户端套接字/*-------------------------------结构体sockaddr_in的注释---------------------------- 头文件:#include<netinet/in.h> struct sockaddr_in { short sin_family;//Address family一般来说AF_INET(地址族)PF_INET(协议族) unsigned short sin_port;//Port number(必须要采用网络数据格式,普通数字可以用htons()函数转换成网络数据格式的数字) struct in_addr sin_addr;//IP address in network byte order(Internet address) unsigned char sin_zero[8];//Same size as struct sockaddr没有实际意义,只是为了跟SOCKADDR结构在内存中对齐;SOCKADDR结构体和该结构体意义一样,16个字节长度。 }; -----------------------------------------------------------------------------------*/ serversocket = socket(AF_INET,SOCK_STREAM,0); /*----------------------------------socket()注释------------------------------------ socket()函数用于根据指定的地址族、数据类型和协议来分配一个套接口的描述字及其所用的资源。 #include <sys/socket.h> int socket( int af, int type, int protocol); af:一个地址描述。目前仅支持AF_INET格式,也就是说ARPA Internet地址格式。 type:指定socket类型。新套接口的类型描述类型,如TCP(SOCK_STREAM)和UDP(SOCK_DGRAM)。 常用的socket类型有,SOCK_STREAM、SOCK_DGRAM、SOCK_RAW、SOCK_PACKET、SOCK_SEQPACKET等等。 protocol:顾名思义,就是指定协议。套接口所用的协议。如调用者不想指定,可用0。 常用的协议有,IPPROTO_TCP、IPPROTO_UDP、IPPROTO_STCP、IPPROTO_TIPC等, 它们分别对应TCP传输协议、UDP传输协议、STCP传输协议、TIPC传输协议。 如果协议protocol未指定(等于0),则使用缺省的连接方式。 ---------------------------------------------------------------------------------*/ if(serversocket == -1) { perror("socket() failed!");//头文件#include<stdio.h>,打印上一步操作的错误信息 return -1; //main()函数返回-1,会导致程序退出。 //return和exit的差别就是前者是返回一个值给函数,退出该函数,而后者是属于系统级别的,将返回值给系统,整个进程退出。 } //初始化服务器套接字,就是将该套接字内容置0; bzero(&server_addr,sizeof(server_addr)); /* 头文件#include <string.h> void bzero(void *s, int n);会将参数s所指的内存区域前n个字节,全部设为零值。*/ //填充服务器套接字server_addr server_addr.sin_family = AF_INET; server_addr.sin_port = htons(portnum);//头文件:#include <arpa/inet.h>, //必须要采用网络数据格式-大端字节序,普通数字可以用htons()函数转换成网络数据格式的数字 server_addr.sin_addr.s_addr = htonl(INADDR_ANY);//设置服务器套接字的IP地址为特殊值INADDR_ANY,这表示服务器愿意接收来自任何网络设备接口的客户机连接。htonl()函数的意思是将主机顺序的字节转换成网络顺序的字节。 /*sin_addr类型是结构体:struct in_addr {in_addr_t s_addr;}; * 其中in_addr_t 一般为 32位的unsigned long. * 其中每8位代表一个IP地址位中的一个数值. * 例如192.168.3.144记为0xc0a80390,其中 c0 为192 ,a8 为 168, 03 为 3 , 90 为 144; * 打印的时候可以调用inet_ntoa()函数将其转换为char *类型. *///注释/*绑定套接字,使用函数: * int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen); * 其头文件为:#include <sys/types.h>和#include <sys/socket.h> * */ if(bind(serversocket,(struct sockaddr *)&server_addr,sizeof(server_addr))==-1) { perror("bind() failed!"); return -1; } /*开始监听 int listen( int sockfd, int backlog);头文件#include <sys/socket.h> sockfd:用于标识一个已捆绑未连接套接口的描述字。 backlog:等待连接队列的最大长度。*/ if(listen(serversocket,10)) { perror("listen() failed!"); return -1; } /*等待 客户端连接 #include <sys/types.h> #include <sys/socket.h> int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen); //调用accept函数后,会进入阻塞状态 //accept返回一个套接字的文件描述符,这样服务器端便有两个套接字的文件描述符, //serverSocket和client_addr。 //serverSocket仍然继续在监听状态,client则负责接收和发送数据 //clientAddr是一个传出参数,accept返回时,传出客户端的地址和端口号 //addr_len是一个传入-传出参数,传入的是调用者提供的缓冲区的clientAddr的长度,以避免缓冲区溢出。 //传出的是客户端地址结构体的实际长度,因此此处必须定义一个addr_len变量 //出错返回-1*/printf("服务器等待连接请求......\n"); //system("gnome-terminal -e ./client pause");/*底下这两行是在启动server的时候,启动当前目录下的client,如果没有客户端,或者客户端不是这个名称,请屏蔽这两行代码*/if(fork()==0)execl("/usr/bin/gnome-terminal","./client pause",NULL);while(1){addr_len = sizeof(client_addr); clientsocket = accept(serversocket, (struct sockaddr*)&client_addr, (socklen_t*)&addr_len); if(clientsocket == -1) { perror("accept() failed!"); return -1; }clientNum++;//客户端个数=子进程编号pid_t cfd;cfd = fork();if(cfd < 0 ){perror("fork():");} else if(cfd == 0){char *numStr;numStr = (char *)malloc(sizeof(char)*3);sprintf(numStr,"%d",clientNum);strcat(clientName,numStr); printf("新的客户端:%s pid:%d IP:%s Port:%d\n",clientName,getpid(),inet_ntoa(client_addr.sin_addr),ntohs(client_addr.sin_port)); //inet_ntoa ip地址转换函数,将网络字节序IP转换为点分十进制IP //表达式:char *inet_ntoa (struct in_addr); while(1){ //接受消息,特别注意第三个参数一定要小于recvbuffer的实际长度。bzero(recvbuffer,sizeof(recvbuffer));ret = recv(clientsocket,recvbuffer,sizeof(recvbuffer)-1,0);if(ret < 0 ) {perror("recv() failed!"); continue; } if(ret == 0 ){ printf("%s已经关闭,服务器继续监听\n");close(clientsocket); break; }recvbuffer[ret]='\0';//如果上面recv()的第三个参数要是等于recvbuffer的长度,//返回的ret也有可能等于这个长度,就会导致此处末尾加'\0出错'printf("收到%s的消息长度:%d 内容:%s\n",clientName,ret,recvbuffer);if(strcmp(recvbuffer,"quit") == 0){ printf("%s:%s停止访问!服务器继续监听\n",clientName,inet_ntoa(client_addr.sin_addr));close(clientsocket); break;} send(clientsocket,recvbuffer,ret,0);} } }return 0;}
阅读全文
2 0
- Linux下C语言TCP编程02
- linux下C语言 socket tcp编程
- Linux下C语言TCP编程01
- C语言Linux下的Socket 编程(TCP)
- Linux下TCP Socket编程C语言小实例
- Linux下TCP Socket编程C语言小实例
- linux下TCP Socket编程C语言小实例
- Linux下TCP Socket编程C语言小实例
- Linux 下 C 语言编程
- Linux下C语言编程
- Linux 下 C 语言编程
- Linux 下 C 语言编程
- linux下C语言编程
- Linux 下 C 语言编程
- Linux下C语言编程
- Linux 下 C 语言编程
- Linux 下 C 语言编程
- Linux下C语言编程
- 购物车实现加减
- FreeRTOS的第一个任务是怎么跑起来的
- C#对文件或图片操作
- Poj 2528 Mayor's posters 线段树
- iframe父子兄弟之间调用传值(contentWindow && parent)
- Linux下C语言TCP编程02
- 私有构造函数可以防止该类在外部被实例化
- Oracle12C--包(四十七)
- 怎么验证交易是否成功
- 线控耳机
- zabbix监控windows进程
- 润乾报表js获取下拉数据集下拉框的显示值
- 461. Hamming Distance
- 一些小问题