900字范文,内容丰富有趣,生活中的好帮手!
900字范文 > Linux网络编程——基于tcp/ip的模拟聊天(文件传输)工具

Linux网络编程——基于tcp/ip的模拟聊天(文件传输)工具

时间:2022-01-06 04:38:16

相关推荐

Linux网络编程——基于tcp/ip的模拟聊天(文件传输)工具

开发平台:Linux

开发工具:Ubuntu, sourceInsight4.0

项目介绍: 本项目基于TCP/IP协议创建一个网络通信系统,可以实现客户之间的聊天通信以及文件传输,同时利用进程实现多客户群聊,多个客户也可同时从服务器下载文件实现文件共享,客户可向服务器发送ls命令获取服务器端的文件目录,并发送get+filename获取文件,也可发送put+filename上传文件到服务器。

protocol.h

#ifndef __PROTOCOL_H__#define __PROTOCOL_H__#define FTP_ROOT_DIR "/home/gec/tftp"//命令号, 命令参数//命令号-> 整数enum CMD_NO {FTP_CMD_LS = 1024, //FTP_CMD_GET,FTP_CMD_PUT,FTP_CMD_BYE,FTP_CMD_NUM // 命令个数};//出错码enum resp_result{RESP_SUCCESS = 0, //成功RESP_PACK_ERROR, //失败,包的长度不对RESP_PACK_NOEND, //包没有结束,可以再次收包RESP_PACK_NOFILE //没有可以获取的文件};//参数: 参数长度, 参数内容/*0xc0 : 包头pkg_len ;//4bytes, 小端模式,整个数据包的长度4(pkg_len) + 4 (cmd_no) + arg_1 +...cmd_no // 4bytes, 小端模式arg_1;arg_1_len; //4bytes , 小端模式arg_1_data; len长度arg_2:arg_2_len; //4bytes,小端模式arg_2_data;....0xC0:包尾*/// cmd: ls//0xc0 ___包长度______ __命令号()__ 0xc0// 0xc0 0x80 0x00 0x00 0x00 //cmd: get//0xc0 ____包长度(4)______命令号(4)___ ___arg_1_Len(4)_ ___filename(r)___ 0xc0#if 0unsigned char cmd[1024];int i = 0;int pkg_len = 1024;cmd[0] = 0xc0;cmd[1] = pkg_len & 0xff;cmd[2] = ( pkg_len >> 8) & 0xff;cmd[3] = (pkg_len >> 16) & 0xff;cmd[4] = (pkg_len >> 24) & 0xff;#endif//CMD_RESP/*0xc0: 包头pkg_len: 整个数据包的长度,4bytes, 小端模式cmd_no : 命令号,4bytes, 小端模式,表示回复哪条命令resp_len: 回复内容的长度,4bytes, 小端模式result + resp_conent1 + xresult: 执行成功或失败,1 bytes , 0表示成功,其他表示失败resp_conent: 回复内容成功:ls: 文件名字 各文件名之间用空格分隔get: 文件大小,4bytes, 小端模式失败:出错码0xc0:包尾*///ls 的回复// 0xc0 --pkg_Len(4)--- ---cmd_No(4)--- --resp_len(4)-- --result(1)-- --filenames(r, 名字以空格分开)--- 0xc0//get 的回复//0xc0 ---pkg_len(4)--- ----cmd_no(4)--- ---resp_len(4)--- ---result(1)-- --file_size(4, 小端模式)--0xc0#endif

tcp_client.c

#include <sys/types.h>/* See NOTES */#include <sys/stat.h>#include <fcntl.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h>#include <linux/socket.h>#include <stdio.h>#include <errno.h>#include <string.h>#include <stdlib.h>#include "protocol.h"int connect_server(char *ip,int port){/**1.创建套接字**/int sockfd = socket(AF_INET,SOCK_STREAM,0);if(-1 == sockfd){perror("socket error");return -1;}/**2.发起链接请求**/int ret;struct sockaddr_in sAddr;memset(&sAddr,0,sizeof(sAddr));sAddr.sin_family = AF_INET;sAddr.sin_port = htons(port);sAddr.sin_addr.s_addr = inet_addr(ip);ret = connect(sockfd,(struct sockaddr*)&sAddr,sizeof(sAddr));if(-1 ==ret){perror("conncet error");return -1;}//return sockfd;}void send_cmd(int sockfd,unsigned char *cmd,int len){//int ret = send(sockfd,cmd,len,0);if(-1 == ret){perror("send cmd error");return;}//}void recv_ls_val(int sockfd){/**服务器回复数据,事先会回复一个数据包0xc0 L E N S E R R N S I Z E 0xc0 回复数据包长度回复的验证信息后续正文大小紧接着服务器会回复正文size个字节的数据**/int i=0;unsigned char ch = 0;unsigned char cmd[500] = {0};/*************************************接收回复数据包*******************************************************///命令以0xc0开头,所以如果收到的不是0xc0则舍弃不要do{//read(sockfd,&ch,1);perror("read ls");}while(ch != 0xc0);////排除连续的0xc0while(ch == 0xc0){read(sockfd,&ch,1);}//确保读取的是数据包的第一个字节//while(ch != 0xc0)//读到的是数据包的内容,读到包尾结束{cmd[i++] = ch;read(sockfd,&ch,1);}/***************************************数据包接收完成*****************************************************//******************************************解析数据包******************************************************///解析包长int cmd_len = cmd[0] | cmd[1]<<8 | cmd[2]<<16 | cmd[3]<<24;if(cmd_len != i){printf("read value error,the pack len is no right\n");//send_error(connfd);return;}//解析验证信息int err_no = cmd[4] | cmd[5]<<8 | cmd[6]<<16 | cmd[7]<<24;if(err_no == RESP_PACK_ERROR){printf("cmd error\n");return;}int data_len = cmd[8] | cmd[9]<<8 | cmd[10]<<16 | cmd[11]<<24;printf("recv data len:%d\n",data_len);/*****************************************解析完毕**********************************************************//****************************************接收回复正文*******************************************************/memset(cmd,0,300);printf("data_len %d\n",data_len);recv(sockfd,cmd,data_len,0);printf("recv data is:%s\n",cmd);}void send_ls(int sockfd){/*ls 命令的数据包:0xc0 L E N SC M D S 0xc04个字节表示包的长度4个字节表示命令*/int i = 0;int pak_len = 4+4;unsigned char cmd[50] ={0};/**********************************组合数据包***************************************************//**帧头**/cmd[i++] = 0xc0;/**包长**/cmd[i++] = pak_len & 0xff;cmd[i++] = pak_len>>8 & 0xff;cmd[i++] = pak_len>>16 & 0xff;cmd[i++] = pak_len>>24 & 0xff;/**命令**/cmd[i++] = FTP_CMD_LS & 0xff;cmd[i++] = FTP_CMD_LS>>8 & 0xff;cmd[i++] = FTP_CMD_LS>>16 & 0xff;cmd[i++] = FTP_CMD_LS>>24 & 0xff;/**帧尾**/cmd[i++] = 0xc0;/******************************数据包组合完毕***************************************************//**发送命令**/send_cmd(sockfd,cmd,i); //将数据包发送出去后,等待服务器的处理结果/**接收返回结果**/recv_ls_val(sockfd);}void recv_get_val(int sockfd,int fd){/**服务器回复数据,事先会回复一个数据包0xc0 L E N S E R R N S I Z E 0xc0 回复数据包长度回复的验证信息后续正文大小紧接着服务器会回复正文size个字节的数据**/int i=0;unsigned char ch = 0;unsigned char cmd[300] = {0};/*************************************接收回复数据包*******************************************************///命令以0xc0开头,所以如果收到的不是0xc0则舍弃不要do{//read(sockfd,&ch,1);}while(ch != 0xc0);//排除连续的0xc0while(ch == 0xc0){read(sockfd,&ch,1);}//确保读取的是数据包的第一个字节while(ch != 0xc0)//读到的是数据包的内容,读到包尾结束{cmd[i++] = ch;read(sockfd,&ch,1);}/***************************************数据包接收完成*****************************************************//******************************************解析数据包******************************************************///解析包长int cmd_len = cmd[0] | cmd[1]<<8 | cmd[2]<<16 | cmd[3]<<24;if(cmd_len != i){printf("read value error,the pack len is no right\n");//send_error(connfd);return;}//解析验证信息int err_no = cmd[4] | cmd[5]<<8 | cmd[6]<<16 | cmd[7]<<24;if(err_no == RESP_PACK_ERROR){printf("cmd error\n");return;}int data_len = cmd[8] | cmd[9]<<8 | cmd[10]<<16 | cmd[11]<<24;printf("recv data len:%d\n",data_len);/*****************************************解析完毕**********************************************************//*****************************************接收文件数据******************************************************/unsigned char *p = (unsigned char *)malloc(data_len+1);int ret=0;while(1){ret += read(sockfd,p+ret,data_len);if(ret == data_len){break;}else if(ret == -1 || ret == 0){perror("read error");return;}}write(fd,p,data_len);//将正文写入本地文件/********************************************判断文件是否发送完成*******************************************************/if(err_no == RESP_PACK_NOEND) //文件内容没有发完,会在后续发送{recv_get_val(sockfd,fd); //再次接收后续包}}void send_get(int sockfd,char *file){/**get命令包格式:0xc0L E N SC M D S S I Z E A R G S . . . .0xc0包长(4bytes) 命令号(6bytes) 参数长度(4bytes)参数正文(size bytes)**/int arg_len = strlen(file);int pak_len = 4+4+4+ arg_len;unsigned char cmd[50] = {0}; //保存命令数据包int i=0;/****************************************封装命令包****************************************************//*包头*/cmd[i++] = 0Xc0;/*包长 小端模式*/cmd[i++] = pak_len & 0xff;cmd[i++] = pak_len>>8 & 0xff;cmd[i++] = pak_len>>16 & 0xff;cmd[i++] = pak_len>>24 & 0xff;/*命令号 小端模式*/cmd[i++] = FTP_CMD_GET & 0xff;cmd[i++] = FTP_CMD_GET>>8 & 0xff;cmd[i++] = FTP_CMD_GET>>16 & 0xff;cmd[i++] = FTP_CMD_GET>>24 & 0xff;/*参数长度*/cmd[i++] = arg_len & 0xff;cmd[i++] = arg_len>>8 & 0xff;cmd[i++] = arg_len>>16 & 0xff;cmd[i++] = arg_len>>24 & 0xff;/*参数正文*/int j=0;for(j=0;j<arg_len;j++){cmd[i++] = file[j];}/*包尾*/cmd[i++] = 0xc0;/********************************************封包完成****************************************************//*发送命令*/send_cmd(sockfd,cmd,i);/*接收回复*/int fd = open(file,O_RDWR|O_CREAT|O_TRUNC,0777);if(-1 == fd){perror("open error");return;}recv_get_val(sockfd,fd);close(fd);}void send_file_data1(int sockfd,int fd,int file_len){/*L E N S E R R N S I Z E*/unsigned char cmd[50] = {0};unsigned char buf[256] = {0};int pak_len;int size;int i;int ret = 0;while(1){size = read(fd,buf,256);if(size == 0 || size==-1){perror("read error");break;}pak_len = 4 + 4 + 4;ret += size;/*帧头*/i = 0;cmd[i++] = 0xc0;/*包长 小端模式*/cmd[i++] = pak_len & 0xff;cmd[i++] = pak_len>>8 & 0xff;cmd[i++] = pak_len>>16 & 0xff;cmd[i++] = pak_len>>24 & 0xff;/*回复码*/if(ret < file_len) //文件没完{cmd[i++] = RESP_PACK_NOEND & 0xff;cmd[i++] = RESP_PACK_NOEND>>8 & 0xff;cmd[i++] = RESP_PACK_NOEND>>16 & 0xff;cmd[i++] = RESP_PACK_NOEND>>24 & 0xff;}else{cmd[i++] = RESP_SUCCESS & 0xff;cmd[i++] = RESP_SUCCESS>>8 & 0xff;cmd[i++] = RESP_SUCCESS>>16 & 0xff;cmd[i++] = RESP_SUCCESS>>24 & 0xff;}/*正文长度*/cmd[i++] = size & 0xff;cmd[i++] = size>>8 & 0xff;cmd[i++] = size>>16 & 0xff;cmd[i++] = size>>24 & 0xff;/*帧尾*/cmd[i++] = 0xc0;send_cmd(sockfd,cmd,i); //回复数据包send(sockfd,buf,size,0); //回复正文}} void send_put(int sockfd,char *file){/**get命令包格式:0xc0L E N SC M D S S I Z E A R G S . . . .0xc0包长(4bytes) 命令号(6bytes) 参数长度(4bytes)参数正文(size bytes)**/int arg_len = strlen(file);int pak_len = 4+4+4+ arg_len;unsigned char cmd[50] = {0}; //保存命令数据包int i=0;/****************************************封装命令包****************************************************//*包头*/cmd[i++] = 0Xc0;/*包长 小端模式*/cmd[i++] = pak_len & 0xff;cmd[i++] = pak_len>>8 & 0xff;cmd[i++] = pak_len>>16 & 0xff;cmd[i++] = pak_len>>24 & 0xff;/*命令号 小端模式*/cmd[i++] = FTP_CMD_PUT & 0xff;cmd[i++] = FTP_CMD_PUT>>8 & 0xff;cmd[i++] = FTP_CMD_PUT>>16 & 0xff;cmd[i++] = FTP_CMD_PUT>>24 & 0xff;/*参数长度*/cmd[i++] = arg_len & 0xff;cmd[i++] = arg_len>>8 & 0xff;cmd[i++] = arg_len>>16 & 0xff;cmd[i++] = arg_len>>24 & 0xff;/*参数正文*/int j=0;for(j=0;j<arg_len;j++){cmd[i++] = file[j];}/*包尾*/cmd[i++] = 0xc0;/********************************************封包完成*****************************************//*发送命令*/send_cmd(sockfd,cmd,i);/*发送文件内容*/int fd = open(file,O_RDONLY);if(-1==fd){perror("open error");return;}int file_len = lseek(fd,0,SEEK_END); //获取文件大小lseek(fd,0,SEEK_SET);send_file_data1(sockfd,fd,file_len); //发送文件内容close(fd);}int main(int argc,char *argv[]){int sockfd = connect_server(argv[1],atoi(argv[2]));if(-1 == sockfd){return -1;}unsigned char cmd[5] = {0};unsigned char file[20] = {0};while(1){memset(cmd,0,5);scanf("%s",cmd);// ls<--- 查看服务器文件列表// get file<--- 从服务器获取文件列表// put file<--- 上传文件到服务器// bye<--- 告知服务器断开链接if( strcmp(cmd,"ls") == 0 ){//send_ls(sockfd);}else if(strcmp(cmd,"get")==0) // get 1.txt{scanf("%s",file);send_get(sockfd,file);}else if(strcmp(cmd,"put")==0){scanf("%s",file);send_put(sockfd,file);}}/**5.处理并退出**/close(sockfd);return 0;}

tcp_server.c

#include <sys/types.h> #include <sys/stat.h> /* See NOTES */#include <fcntl.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h>#include <linux/socket.h>#include <stdio.h>#include <errno.h>#include <string.h>#include <stdlib.h>#include <dirent.h>#include "protocol.h"#define FTP_DIR "/home/gec/tftp"void send_pack(int connfd,unsigned char *cmd,int len){//printf("%d %x\n",connfd,cmd[0]);int ret = send(connfd,cmd,len,0);if(-1 == ret){perror("send cmd error");return;}//}void send_error(int connfd){int i = 0;int pak_len = 4+4;unsigned char cmd[50] ={0};/**帧头**/cmd[i++] = 0xc0;/**包长**/cmd[i++] = pak_len & 0xff;cmd[i++] = pak_len>>8 & 0xff;cmd[i++] = pak_len>>16 & 0xff;cmd[i++] = pak_len>>24 & 0xff;/**错误码**/cmd[i++] = RESP_PACK_ERROR & 0xff;cmd[i++] = RESP_PACK_ERROR>>8 & 0xff;cmd[i++] = RESP_PACK_ERROR>>16 & 0xff;cmd[i++] = RESP_PACK_ERROR>>24 & 0xff;/**帧尾**/cmd[i++] = 0xc0;/**发送回复数据**/send_pack(connfd,cmd,i);}void repa_ls(int connfd){int i = 0;int pak_len = 0;unsigned char file[500] = {0};unsigned char cmd[500] = {0};DIR *dirp = opendir(FTP_DIR);if(NULL == dirp){perror("open dir error");return ;}//struct dirent *dir;while((dir = readdir(dirp)) != NULL){sprintf(file+strlen(file),"%s ",dir->d_name);printf("%d %s\n",strlen(file),dir->d_name);}///**帧头**/cmd[i++] = 0xc0;/**包长**/pak_len = 4 + 4 + 4;cmd[i++] = pak_len & 0xff;cmd[i++] = pak_len>>8 & 0xff;cmd[i++] = pak_len>>16 & 0xff;cmd[i++] = pak_len>>24 & 0xff;/**错误码**/cmd[i++] = RESP_SUCCESS & 0xff;cmd[i++] = RESP_SUCCESS>>8 & 0xff;cmd[i++] = RESP_SUCCESS>>16 & 0xff;cmd[i++] = RESP_SUCCESS>>24 & 0xff;/**回复数据长度**/cmd[i++] = strlen(file) & 0xff;cmd[i++] = strlen(file)>>8 & 0xff;cmd[i++] = strlen(file)>>16 & 0xff;cmd[i++] = strlen(file)>>24 & 0xff;printf("recv ls data size %d\n",strlen(file));printf("%s\n",file);/**帧尾**/cmd[i++] = 0xc0;send_pack(connfd,cmd,i); //回复命令的处理结果send_pack(connfd,file,strlen(file));//回复命令数据//}void send_file_data(int connfd,int fd,int file_len){/*L E N S E R R N S I Z E*/unsigned char cmd[50] = {0};unsigned char buf[256] = {0};int pak_len;int size;int i;int ret = 0;while(1){size = read(fd,buf,256);if(size == 0 || size==-1){perror("read error");break;}pak_len = 4 + 4 + 4;ret += size;/*帧头*/i = 0;cmd[i++] = 0xc0;/*包长 小端模式*/cmd[i++] = pak_len & 0xff;cmd[i++] = pak_len>>8 & 0xff;cmd[i++] = pak_len>>16 & 0xff;cmd[i++] = pak_len>>24 & 0xff;/*回复码*/if(ret < file_len) //文件没完{cmd[i++] = RESP_PACK_NOEND & 0xff;cmd[i++] = RESP_PACK_NOEND>>8 & 0xff;cmd[i++] = RESP_PACK_NOEND>>16 & 0xff;cmd[i++] = RESP_PACK_NOEND>>24 & 0xff;}else{cmd[i++] = RESP_SUCCESS & 0xff;cmd[i++] = RESP_SUCCESS>>8 & 0xff;cmd[i++] = RESP_SUCCESS>>16 & 0xff;cmd[i++] = RESP_SUCCESS>>24 & 0xff;}/*正文长度*/cmd[i++] = size & 0xff;cmd[i++] = size>>8 & 0xff;cmd[i++] = size>>16 & 0xff;cmd[i++] = size>>24 & 0xff;/*帧尾*/cmd[i++] = 0xc0;send_pack(connfd,cmd,i); //回复数据包send(connfd,buf,size,0); //回复正文}} void repa_get(int connfd,unsigned char *cmd){/************************************解析get参数*******************************************************/int i = 8;int arg_len = cmd[8] | cmd[9]<<8 | cmd[10]<<16 | cmd[11]<<24;char *file = (char *)malloc(arg_len+1);memset(file,0,arg_len+1);for(i=0;i<arg_len;i++){file[i] = cmd[12+i]; //获取文件名}/************************************打开文件读取数据并准备回复************************************************/int pak_len = 0;i=0;char ftp_file[100] = {0};sprintf(ftp_file,"%s/%s",FTP_DIR,file);int fd = open(ftp_file,O_RDONLY);if(-1 == fd){perror("open error");/*帧头*/cmd[i++] = 0xc0;pak_len = 8;/*包长 小端模式*/cmd[i++] = pak_len & 0xff;cmd[i++] = pak_len>>8 & 0xff;cmd[i++] = pak_len>>16 & 0xff;cmd[i++] = pak_len>>24 & 0xff;/*回复码*/cmd[i++] = RESP_PACK_NOFILE & 0xff;cmd[i++] = RESP_PACK_NOFILE>>8 & 0xff;cmd[i++] = RESP_PACK_NOFILE>>16 & 0xff;cmd[i++] = RESP_PACK_NOFILE>>24 & 0xff;/*帧尾*/cmd[i++] = 0xc0;send_pack(connfd,cmd,i);}else{int file_len = lseek(fd,0,SEEK_END); //获取文件大小lseek(fd,0,SEEK_SET);send_file_data(connfd,fd,file_len); //回复文件内容close(fd);}}void recv_get_val1(int connfd,int fd){/**服务器回复数据,事先会回复一个数据包0xc0 L E N S E R R N S I Z E 0xc0 回复数据包长度回复的验证信息后续正文大小紧接着服务器会回复正文size个字节的数据**/int i=0;unsigned char ch = 0;unsigned char cmd[300] = {0};/*************************************接收回复数据包*******************************************************///命令以0xc0开头,所以如果收到的不是0xc0则舍弃不要do{//read(connfd,&ch,1);}while(ch != 0xc0);//排除连续的0xc0while(ch == 0xc0){read(connfd,&ch,1);}//确保读取的是数据包的第一个字节while(ch != 0xc0)//读到的是数据包的内容,读到包尾结束{cmd[i++] = ch;read(connfd,&ch,1);}/***************************************数据包接收完成*****************************************************//******************************************解析数据包******************************************************///解析包长int cmd_len = cmd[0] | cmd[1]<<8 | cmd[2]<<16 | cmd[3]<<24;if(cmd_len != i){printf("read value error,the pack len is no right\n");//send_error(connfd);return;}//解析验证信息int err_no = cmd[4] | cmd[5]<<8 | cmd[6]<<16 | cmd[7]<<24;if(err_no == RESP_PACK_ERROR){printf("cmd error\n");return;}int data_len = cmd[8] | cmd[9]<<8 | cmd[10]<<16 | cmd[11]<<24;printf("recv data len:%d\n",data_len);/*****************************************解析完毕**********************************************************//*****************************************接收文件数据******************************************************/unsigned char *p = (unsigned char *)malloc(data_len+1);int ret=0;while(1){ret += read(connfd,p+ret,data_len);if(ret == data_len){break;}else if(ret == -1 || ret == 0){perror("read error");return;}}write(fd,p,data_len);//将正文写入本地文件/********************************************判断文件是否发送完成*******************************************************/if(err_no == RESP_PACK_NOEND) //文件内容没有发完,会在后续发送{recv_get_val1(connfd,fd); //再次接收后续包}}void repa_put(int connfd,unsigned char *cmd){int i = 8;int arg_len = cmd[8] | cmd[9]<<8 | cmd[10]<<16 | cmd[11]<<24;char *file = (char *)malloc(arg_len+1);memset(file,0,arg_len+1);for(i=0;i<arg_len;i++){file[i] = cmd[12+i]; //获取文件名}char ftp_file[100] = {0};sprintf(ftp_file,"%s/%s",FTP_DIR,file);int fd = open(ftp_file,O_RDWR|O_CREAT|O_TRUNC,0777);if(-1 == fd){perror("open error");return;}recv_get_val1(connfd, fd);}int recv_cmd(int connfd){int i=0;unsigned char ch = 0;unsigned char cmd[50] = {0};while(1){//命令以0xc0开头,所以如果收到的不是0xc0则舍弃不要do{read(connfd,&ch,1);}while(ch != 0xc0);//排除连续的0xc0while(ch == 0xc0){read(connfd,&ch,1);}//确保读取的是数据包的第一个字节i=0;while(ch != 0xc0)//读到的是数据包的内容,读到包尾结束{cmd[i++] = ch;read(connfd,&ch,1);}int cmd_len = cmd[0] | cmd[1]<<8 | cmd[2]<<16 | cmd[3]<<24;if(cmd_len != i){printf("read cmd error,the pack len is no right\n");send_error(connfd);return 0;}int cmd_num = cmd[4] | cmd[5]<<8 | cmd[6]<<16 | cmd[7]<<24;switch(cmd_num)//判断收到的命令{case FTP_CMD_LS:repa_ls(connfd);break;case FTP_CMD_GET:repa_get(connfd,cmd);break;case FTP_CMD_PUT:repa_put(connfd,cmd);break;}}}int main(int argc,char *argv[]){/**1.创建套接字**/int sockfd = socket(AF_INET,//IPv4协议族SOCK_STREAM,//流式套接字0//默认协议);if(-1 == sockfd){perror("socket error");return -1;}/**设置套接字选项**/int val = 1;setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&val,4);//允许地址重用setsockopt(sockfd,SOL_SOCKET,SO_REUSEPORT,&val,4);//允许端口重用/**2.绑定地址**/struct sockaddr_in sAddr;//以太网协议地址结构体 <--- 方便赋值memset(&sAddr,0,sizeof(sAddr));sAddr.sin_family = AF_INET;//协议族sAddr.sin_port = htons(atoi(argv[2]));//网络字节序的短整型sAddr.sin_addr.s_addr =inet_addr(argv[1]);//网络字节序的u32整数int ret;ret = bind(sockfd,//绑定的套接字(struct sockaddr*)&sAddr,//该套接字绑定的"地址"sizeof(sAddr)//地址长度);//将套接字与"地址"绑定if(-1 == ret){perror("bind error");return -1;}/**3.设置监听**/ret = listen(sockfd,10);if(-1 == ret){perror("listen error");return -1;}/**4.等待链接**/int connfd;struct sockaddr_in cAddr;socklen_t addrlen = sizeof(cAddr);while(1){connfd = accept(sockfd,//套接字描述符,表示等待那个套接字上的链接(struct sockaddr*)&cAddr,//"地址"空间,用来保存客户端的地址&addrlen//空间,用来保存客户端地址长度);//如果有客户端链接,服务器端接受请求并返回链接描述符//链接描述符是用来与 对应的客户端进行通信if(-1 == connfd){perror("accept error");return -1;}printf("connect client is:%s:%d\n",inet_ntoa(cAddr.sin_addr),ntohs(cAddr.sin_port));pid_t pid = fork();if(pid > 0){close(connfd);continue;}else if(pid == 0){//recv_cmd(connfd);exit(0);}}/**7.处理并退出**/close(sockfd);close(connfd);return 0;}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。