1.标准的server client模型
/*sever.c*/
#include <sys/types.h>
#include <sys/socket.h>
#include <strings.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <arpa/inet.h>
#define SERV_PORT 8000
void perr_exit(const char *str)
{
perror(str);
exit(1);
}
int main()
{
int sfd = socket(AF_INET,SOCK_STREAM,0),cfd;
struct sockaddr_in servaddr;
struct sockaddr_in client_addr;
int i,len;
socklen_t addr_len;
//init
bzero(&servaddr,sizeof(struct sockaddr_in));
servaddr.sin_family = AF_INET;
//htons htonl 都属于网络字节序转换,在代码段之后会进行解释,就先理解为转换为网络中所需要的类型
servaddr.sin_port = htons(SERV_PORT);
//INADDR_ANY表示任意都可连接(因为客户端不是来自同一个网络地址)
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);//
if(bind(sfd,(struct sockaddr *)&servaddr,sizeof(servaddr)) < 0)
perr_exit("bind error");
//设置可连接数为128
listen(sfd,128);
printf("wait for conncet---------\n");
addr_len = sizeof(client_addr);
cfd = accept(sfd,(struct sockaddr *)&client_addr,&addr_len);
if(cfd == -1)
perr_exit("accept error");
char buf[256];
/*系统还为我们封装了IP地址转换函数
* 因为IP地址在网络中为网络字节序二进制值,而我们平常使用的是ASCII字符串,
* 故有这一组函数来进行转换,其实也不难记,可以这样形式的记住,以免用混ip to net,net to ip
* #include <arpa/inet.h>
* int inet_pton(int af, const char *src, void *dst);
* const char *inet_ntop(int af, const void *src, char *dst, socklen_t size);
* */
printf("client IP :%s %d\n",
inet_ntop(AF_INET,&client_addr.sin_addr.s_addr,buf,sizeof(buf)),
ntohs(client_addr.sin_port));
while(1)
{
len = read(cfd,buf,sizeof(buf)); //读取客户端的数据
if(len == -1)
perr_exit("read error");
/*
if(len == 0)
{
printf("the other size closed\n");
close(cfd);
close(sfd);
exit(1);
}
*/
if(write(STDOUT_FILENO,buf,len) < 0) //输出到屏幕
perr_exit("write error");
for(i = 0 ;i < len ; i++) //进行大写转换
buf[i] = toupper(buf[i]);
if(write(cfd,buf,len) < 0) //写数据到客户端
perr_exit("write error");
}
//关闭打开的文件描述符,虽然不会执行到这里往下的部分,但要养成良好习惯,打开文件描述符,用完
//就要关闭
close(sfd);
close(cfd);
return 0;
}
/*client.c*/
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <string.h>
#include <arpa/inet.h>
#define SERV_PORT 8000
void perr_exit(const char *str)
{
perror(str);
exit(1);
}
int main(int argc,char *argv[])
{
int sfd,len;
sfd = socket(AF_INET,SOCK_STREAM,0);
char buf[256];
struct sockaddr_in serv_addr;
bzero(&serv_addr,sizeof(serv_addr));
//init
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(SERV_PORT);
inet_pton(AF_INET,argv[1],&serv_addr.sin_addr.s_addr);//转换char *IP地址为网络二进制序
if(connect(sfd,(struct sockaddr*)&serv_addr,sizeof(serv_addr)) < 0)
perr_exit("connect error");
while(fgets(buf,sizeof(buf),stdin))//读取终端输入的数据
{
if(write(sfd,buf,strlen(buf)) < 0)//写入数据到服务器
perr_exit("write error");
len = read(sfd,buf,sizeof(buf));//读取服务器传递的数据
if(len <0)
perr_exit("read error");
if(len == 0)
{
printf("the other size closed\n");
close(sfd);
exit(1);
}
if(write(STDOUT_FILENO,buf,len) < 0)//输出到终端
perr_exit("write error");
}
return 0;
}
运行刚编写的程序,遇到segmentation fault (core dumped) (段错误),在网上查找到调试方法如下:
1.让系统在信号中断造成的错误时产生core文件
修改core文件大小,需要su权限:
查看core文件设置
ulimit -a
设置core大小为无限
ulimit -c unlimited
设置文件大小为无限
ulimit unlimited
- 用gdb查看core文件:
下面我们可以在发生运行时信号引起的错误时发生core dump了.
发生core dump之后, 用gdb进行查看core文件的内容, 以定位文件中引发core dump的行.
gdb [exec file] [core file]
例如:
gdb a.out core.8564
利用命令where查看错误位置
inet_aton(const * str, srtuct in_addr *addrptr);把str转换成32位的网络字节序二进制值
inet_addr(const char * str);把str转换成32位的网络字节序的二进制值,错误会返回255.255.255.255
转自 https://blog.csdn.net/zero_witty/article/details/54920148