开发平台: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 0
unsigned 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 S                C 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命令包格式:0xc0     L E N S      C 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命令包格式:0xc0     L E N S      C 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;
}

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

  1. 两台linux电脑在互联网内传输文件,linux网络编程之实现跨平台PC之间进行文件传输...

    //实现两台计算机进行文件传输,包括跨平台传输即linux与windows之间 //TCP的文件传输 //文件大小不限制,需要做到将大文件分包去做 server.c //服务端程序 int main( ...

  2. 网络编程——基于TCP协议的通讯录【课程设计】

    网络编程--基于TCP协议的通讯录[课程设计] 本文目录 网络编程--基于TCP协议的通讯录[课程设计] 一.设计题目和要求 设计目标: 课程设计系统组成及模块功能: 二.设计内容 服务端 客户端 S ...

  3. 【Linux网络编程】TCP带外数据

    [Linux网络编程]TCP带外数据 [1]TCP 包的部首 TCP带外数据相关概念 紧急字段URG     : 当URG=1时,告诉系统此报文段中有紧急数据,应尽快传送. 紧急指针         ...

  4. 项目实战:基于 TCP 的局域网内高性能文件传输系统设计与实现

    本项目开发基于 Red Hat Enterprise Linux(RHEL) 6.3 平台 ,通过本项目大家会深入理解下述内容: Socket 网络编程技术 基于TCP/IP 协议的网络编程技术 基于 ...

  5. QT从入门到入土(九)——TCP/IP网络通信(以及文件传输)

    引言 TCP/IP通信(即SOCKET通信)是通过网线将服务器Server端和客户机Client端进行连接,在遵循ISO/OSI模型的四层层级构架的基础上通过TCP/IP协议建立的通讯.控制器可以设置 ...

  6. 【Linux网络编程】TCP编程

    00. 目录 文章目录 00. 目录 01. TCP概述 02. TCP特点 03. TCP中CS架构 04. TCP相关函数 05. TCP服务端示例 06. TCP客户端示例 07. 附录 01. ...

  7. 【Linux网络编程】TCP三次握手和四次挥手

    00. 目录 文章目录 00. 目录 01. 三次握手 02. 四次挥手 03. 三次握手和四次挥手原因 04. 2MSL 05. 附录 01. 三次握手 在 TCP/IP 协议中,TCP 协议提供可 ...

  8. 【Linux网络编程】TCP网络编程中connect listen和accept三者之间的关系

    00. 目录 文章目录 00. 目录 01. TCP服务端和客户端流程 02. connect函数 03. listen函数 04. 三次握手 05. accept函数 06. 附录 01. TCP服 ...

  9. step5 . day6 网络编程 基于TCP协议的多并发模式(使用多进程、多线程、select函数分别实现)...

    实现TCP服务器端多路并发的方法有①多进程②多线程③IO多路复用(select poll epoll函数) 1.多进程实现并发模式(仅在服务器端更改之前代码实现) 服务器端 #include < ...

最新文章

  1. FastDFS之Linux下搭建
  2. linux-----shell高级编程----grep应用
  3. Windows Vista for Developers——第三部分补充:控件和桌面窗口管理器
  4. SQLSERVER常用函数汇总
  5. python处理excel案例_python操作excel例子
  6. Python数据存储:pickle模块的使用讲解(测试代码)
  7. 人工智能大脑如何调控智能交通“疏堵”?
  8. 保留12位小数的浮点数(信息学奥赛一本通-T1025)
  9. android启动界面修改工具,Android 系统界面调节工具使用及功能
  10. 招聘云计算、虚拟化、前端开发、测试等工程师
  11. linux mysql 开发_Linux64下mysql安装和开发
  12. Java的测试方法有哪些?自动化测试让Java测试变得更简单!
  13. PaddleOCR 手写识别模型:标注到训练
  14. 在windows系统下制作虚拟软驱
  15. 小白莲的操作系统day05-2.3(01-05)
  16. VC写的双人版俄罗斯方块
  17. Selective Search算法-候选框生成
  18. 用100元换10元、5元和1元的纸币共50张,能换各种纸币多少张。
  19. 速途研究院联合融云:中国移动社交沟通指数报告
  20. Python实现undo操作

热门文章

  1. 深入浅出pytorch笔记——第一章
  2. VMware虚拟机怎么安装ghost系统
  3. php命名空间namespace自动载入
  4. zk4元年拆解_科比zk4复刻前掌没有zoom zk4选秀日复刻中底拆解测评
  5. [ 数通面试 ] 奇安信技术支持工程师 面试分享
  6. 【SAP消息号KI344】
  7. FME会员期刊(2012秋季版)——更新完毕
  8. 为什么默认排除 junit-vintage-engine ?
  9. 结构方程模型的R语言实现
  10. 为什么结构方程模型路径系数很大却不显著?