完成一个Linux下的网络通信程序,该程序包括服务器和客户端两部分,且能够互相通信,传递消息,传送文件,即时聊天。
该系统主要功能为发送接收消息和文件,次要功能为功能选择、退出等。
该系统是服务器与客户端之间进行通信,同时涉及到文件读取与存储,故还与文件系统有交互,所以抽取出服务器、客户端、文件系统三个交互方。服务器和客户端之间通过系统可以进行消息、文件的收发,同时系统可以处理服务器和客户端的操作,如功能选择、退出等。
系统需要进行初始化,完成连接,服务器可以选择需要的功能,与客户端进行通信,收发并处理数据,可以退出程序。客户端可以选择需要的功能,与服务器进行通信,收发并处理数据,可以退出程序。
系统初始化时服务器建立监听端口,用于与客户端建立连接,客户端会发送地址和端口信息,与服务器建立连接。服务器客户端均可通过功能选择选择收发消息或收发文件的功能。
系统分为服务器和客户端两个独立的程序,通过socket进行通信,采用IPv4,TCP协议进行传输。可以通过输入C或F进行选择功能,C为发送消息,F为发送文件。发送消息按下回车后,接收方能够显示收到的消息,发送文件时接收方接收完毕后会显示接收的文件名以及文件存储的位置,同时会反馈给发送方,发送方会显示对方已接收文件。可以通过发送消息模式输入quit退出系统。当选择模式时输入非C或非F,系统会告知用户暂未开通此功能,敬请期待,仍可重新选择功能。
服务器
程序初始化;
持续监听一个固定的端口;
收到Client的连接后建立一个socket连接;
与Client进行通信和信息处理;
接收Client通过socket连接发送来的数据,进行相应处理并返回结果;
通信结束后中断与Client的连接.
客户端
程序初始化;
链接到某个Server上,建立socket连接;
与Server进行通信和信息处理;
接收Server通过socket连接发送来的数据,进行相应处理;
通过socket连接向Server发送请求信息;
通信结束后中断与Server的连接[1].
int get_sockfd()
{
struct sockaddr_in server_addr;
if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)
{
fprintf(stderr,"创建套接字错误:%s\n\a",strerror(errno));
exit(1);
}
else
{
printf("创建套接字成功!\n");
}
/*sockaddr结构 */
bzero(&server_addr,sizeof(server_addr));
server_addr.sin_family=AF_INET;
server_addr.sin_port=htons(SERVER_PORT);
server_addr.sin_addr.s_addr=htonl(INADDR_ANY);
int opt = 1;
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
/*绑定服务器的ip和服务器端口号*/
if(bind(sockfd,(struct sockaddr *)(&server_addr), sizeof(server_addr)) == -1){
fprintf(stderr,"端口绑定错误:%s\n\a",strerror(errno));
exit(1);
}
else{
printf("端口绑定成功!\n");
}
/* 设置允许连接的最大客户端数 */
if(listen(sockfd,BACKLOG)==-1){
fprintf(stderr,"监听端口错误:%s\n\a",strerror(errno));
exit(1);
}
else{
printf("端口监听中......\n");
}
return sockfd;
}
void sendMsg(char sendbuf[], int socket)
{
printf("你:");
scanf("%s", sendbuf);
if(send(socket, sendbuf, strlen(sendbuf), 0) < 0)
{
printf("消息发送失败!\n");
}
}
void receiveMsg(char recvbuf[], char their_name[], int socket)
{
int iDataNum;
printf("%s:", their_name);
recvbuf[0] = '\0';
if((iDataNum = recv(socket, recvbuf, SIZE, 0)) < 0)
{
printf("数据接收失败!\n");
}
recvbuf[iDataNum] = '\0';
printf("%s\n", recvbuf);
}
int sendFile(char sendbuf[], char file_name[], int socket)
{
// 打开文件并读取文件数据
FILE *fp = fopen(file_name, "r");
if(NULL == fp)
{
printf("%s 文件不存在!\n", file_name);
}
else
{
bzero(sendbuf, SIZE);
int length = 0;
// 每读取一段数据,便将其发送给服务器,循环直到文件读完为止
while((length = fread(sendbuf, sizeof(char), SIZE, fp)) > 0)
{
if(send(socket, sendbuf, length, 0) < 0)
{
printf("%s 发送失败\n", file_name);
break;
}
bzero(sendbuf, SIZE);
}
fclose(fp);
printf("%s 发送成功!\n", file_name);
int iDataNum;
char recvbuf[SIZE];
bzero(recvbuf,SIZE);
recvbuf[0] = '\0';
//接收对方接收完文件后的反馈信息
if((iDataNum = recv(socket, recvbuf, SIZE, 0)) < 0)
{
printf("数据接收失败!\n");
}
recvbuf[iDataNum] = '\0';
if(strcmp(recvbuf, "success")==0)
{
printf("对方已接收文件!\n");
}
}
return 0;
}
int receiveFile(char recvbuf[], char file_name[], int socket)
{
// 打开文件,准备写入
FILE *fp = fopen(file_name, "w");
if(NULL == fp)
{
printf("无法写入文件%s.\n", file_name);
exit(1);
}
// 从服务器接收数据到recvbuf中
// 每接收一段数据,便将其写入文件中,循环直到文件接收完并写完为止
bzero(recvbuf, SIZE);
int length = 0;
while(1)
{
length = recv(socket, recvbuf, SIZE, 0);
if(length > 0){
if(fwrite(recvbuf, sizeof(char), length, fp) < length)
{
printf("写入文件%s失败\n", file_name);
break;
}
bzero(recvbuf, SIZE);
}
break;
}
fclose(fp);
printf("成功接收文件:%s! 文件存储在默认文件夹下(程序所在文件夹).\n", file_name);
char sendbuf[SIZE]="success";
send(socket, sendbuf, strlen(sendbuf), 0);
return 0;
}