您的位置:首页 > 理论基础 > 计算机网络

linux网络编程简单C/S模型实现

2017-09-23 23:32 471 查看

Talk is cheap,show me the code

server.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h> //类unix系统中,对系统调用的封装接口
//如提供通用的文件、目录、程序、及进程操作的函数
#include <errno.h> //提供错误号error定义,用于错误处理
#include <sys/socket.h> //提供socket函数及数据结构
#include <sys/types.h> //数据类型定义
#include <netinet/in.h> //定义数据结构sockaddr_in
#include <arpa/inet.h> //提供IP地址转换函数

#define MAXLINE 255 //最大接受字节数

/*一切皆socket*/
/*socket套接字概念介绍*/
/*Unix/Linux基本哲学:“一切皆文件”
* Socket就是该模式的实现,是一种特殊的文件
* 一些socket函数就是对其进行操作,如读写,打开,关闭
* socket为应用层与TCP/IP协议族通信的中间软件抽象层,是一组接口
* 让socket去组织数据,以符合指定的协议*/

int main(int argc,char** argv)
{
int lis_fd,con_fd; //套接字描述符
/*其实为一个整数,如所熟悉的0、1、2对应的FILE*结构为stdin、stdout、stderr
* 记录操作系统函数返回的一个整数作为描述符来标识套接字socket
* 接着,再以此描述符作为传递参数,调用函数完成某种操作*/

struct sockaddr_in serv_addr,clit_addr; //IPV4地址结构
socklen_t clit_len;
char buf[MAXLINE]={0}; //缓冲区
int i,n,port;

if(argc<3){
printf("please fill the parameter\n");
return 1;
}
//服务器端开始建立监听socket描述符,唯一标识一个socket
//第一个参数protofamily协议域、二type指定socket类型、三protocol指定协议
//返回socket描述字符位于协议族空间中,但无具体的地址
//通过bind函数赋予地址,或connect/listen时随机分配
if(-1 == (lis_fd=socket(AF_INET,SOCK_STREAM,0))){
perror("socket error\n");
exit(1);
}
//初始化
bzero(&serv_addr,sizeof(serv_addr));
//memset(&serv_addr,0,sizeof(serv_addr));

//服务器填充sockaddr结构
serv_addr.sin_family=AF_INET; //设置地址类型 IPV4
//serv_addr.sin_addr.s_addr=htonl(INADDR_ANY); //设置IP地址,让系统自动获取本机IP地址
serv_addr.sin_addr.s_addr=inet_addr(argv[1]);
port=atoi(argv[2]);
serv_addr.sin_port=htons(port); //设置默认端口号

//函数bind将服务器的本地地址和套接字绑定
if(-1==bind(lis_fd,(struct sockaddr*)&serv_addr,sizeof(struct sockaddr))){
perror("bind error\n");
exit(1);
}
//listen函数提醒内核,此套接字可接受客户端请求,开始监听
if(listen(lis_fd,10)==-1){ //第二个参数为socket可排队的最大连接数
perror("listen error\n");
exit(1);
}

printf("========waiting for client's request===========\n");

/*处理客户端请求,通过accept函数获得与一个客户端的连接*/
clit_len=sizeof(struct sockaddr_in);
//accept返回的是已连接socket套接字描述符,不同于之前的监听描述符,且默认阻塞进程
if(-1==(con_fd=accept(lis_fd,(struct sockaddr*)&clit_addr,&clit_len))){
perror("accept error\n");
exit(1);
}
printf("connect from %s:%u...!\n",inet_ntoa(clit_addr.sin_addr),ntohs(clit_addr.sin_port));

while(1){
//接受客户端发送来的数据
memset(buf,0,MAXLINE);
if((n=recv(con_fd,buf,MAXLINE,0))==0){
sleep(1); //linux的sleep默认睡1秒
continue;
}

buf
=0;
printf("recv msg from client: %s\n",buf);
if(0 == strncmp(buf,"quit",4)){
break;
}
if(0 == strncmp(buf,"send",4)){
memset(buf,0,MAXLINE);
scanf("%s",&buf);
send(con_fd,buf,strlen(buf),0);
}
}
close(con_fd);
close(lis_fd);
exit(0);
}


client.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define MAXLINE 255

int main(int argc,char** argv)
{
int sockfd,n,rec_len,port;
char recvline[MAXLINE],sendline[MAXLINE];
struct sockaddr_in conn_addr;
if(argc<3){
printf("please fill the parameter\n");
return 1;
}
//if(sockfd=socket(AF_INET,SOCK_STREAM,0)<0){
//优先级问题,sockfd接受比较后的01,没有得到正确的描述符
//找了一晚上的bug。。。心态大崩
//大家以后以此为戒,勤加括号,避免粗心大意
if((sockfd=socket(AF_INET,SOCK_STREAM,0))<0){
perror("socket error\n");
exit(1);
}
bzero(&conn_addr,sizeof(conn_addr));
conn_addr.sin_family=AF_INET;
port=atoi(argv[2]); //端口号,字符串转换至整型
conn_addr.sin_port=htons(port);
conn_addr.sin_addr.s_addr=inet_addr(argv[1]);
/*
if(inet_pton(AF_INET,argv[1],&conn_addr.sin_addr)<=0){ //转换字符串到网络地址
printf("exchange error\n");
exit(1);
}*/
if(connect(sockfd,(struct sockaddr*)&conn_addr,sizeof(conn_addr))<0){
printf("connect error: %s(error: %d)\n",strerror(errno),errno);
exit(1);
}

printf("send msg to server: \n");
while(1){
memset(sendline,0,MAXLINE);
fgets(sendline,MAXLINE,stdin);
if(send(sockfd,sendline,strlen(sendline),0)<0){
printf("send error\n");
exit(1);
}
memset(recvline,0,MAXLINE);
if((rec_len=recv(sockfd,recvline,MAXLINE,0))==-1){
printf("recv error\n");
exit(1);
}
recvline[rec_len]='\0';
if(0 == strncmp(recvline,"quit",4)) break;
printf("Received: %s\n",recvline);
}
close(sockfd);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息