目录
socket套接字网络通信学习
数据协议
tcp
udp
ip地址
端口
字节序
步骤
API介绍
地址转换API
实战 聊天对话框
服务器 运行时后面要传IP地址和端口
客户端 运行时后面要传IP地址和端口
socket是网络通信,通信的数据协议有http、tcp、udp等等,简单来说就是传输数据的格式,常用的是tcp和udp
要网络通信,那少不了的就是IP地址和端口号,ip地址是你与谁的机子通信,端口是指机子里的哪个服务通信,一台机子有很多端口
字节序是指多字节数据在计算机内存存储或者网络传输时各个字节的存储顺序
例如存储0x01 0x02 0x03 0x04这四个数据到为 2000 2001 2002 2003这四个地址里
我们将0x1234abcd写入到以0x0000开始的内存中
我们只需要调用socket的api进行通信就可以,api会调用内核帮我们实现
#include
#include
#include
#include
#include
#include
#include
int main(int argc, char **argv)
{
int s_fd;//服务端描述符
int c_fd;//客户端描述符
int n_read;//读了多少字节
char readBuf[128];//收到的数据缓存
int mark = 0;//记录第几个连接标识符
char msg[128] = {0};//发送的数据缓存
struct sockaddr_in s_addr;//自己服务端的协议机构提
struct sockaddr_in c_addr;//已连接的客户端的协议结构体
//如果后面没有两个参数,退出
if(argc != 3){
printf("param is not good\n");
exit(-1);
}
memset(&s_addr,0,sizeof(struct sockaddr_in));//
memset(&c_addr,0,sizeof(struct sockaddr_in));//
//1. 创建socket AF_INET为ipv4协议 SOCK_STREAM为面向连接的通信流,tcp协议,0是自动匹配对应协议
s_fd = socket(AF_INET, SOCK_STREAM, 0);
if(s_fd == -1){
perror("socket");
exit(-1);
}
s_addr.sin_family = AF_INET;//记录上面的协议族ipv4协议
s_addr.sin_port = htons(atoi(argv[2]));//将字符串端口号转为数字然后转为网络字符
inet_aton(argv[1],&s_addr.sin_addr);//将ip地址转为网络字符放到sin_addr里
//2. bind连接 s_fd是socket描述符 &s_addr是存放socket信息的结构体 sizeof...是结构体的大小
bind(s_fd,(struct sockaddr *)&s_addr,sizeof(struct sockaddr_in));
//3. listen监听 s_fd是socket描述符 10是最多有十个人同时连接
listen(s_fd,10);
//4. accept接入
int clen = sizeof(struct sockaddr_in);//是存放socket信息的结构体的大小
while(1){
// s_fd是socket描述符 &c_addr是已连接的客户端的协议结构体 &clen是存放socket信息的结构体的大小
c_fd = accept(s_fd,(struct sockaddr *)&c_addr,&clen);
if(c_fd == -1){
perror("accept");
}
mark++;//记录第几个连接标识符
printf("get connect: %s\n",inet_ntoa(c_addr.sin_addr));//打印客户端的IP地址
//创建线程
if(fork() == 0){
//write写
if(fork()==0){//子线程一直循环发送第几个连接对象,等于心跳包
while(1){
sprintf(msg,"welcom No.%d client",mark);
write(c_fd,msg,strlen(msg));//向描述符发送msg消息
sleep(3);
}
}
//5. read读
while(1){
memset(readBuf,0,sizeof(readBuf));//清空收到的数据
n_read = read(c_fd, readBuf, 128);//接收描述符对应的socket消息,放到readbuf里,最大读128字节
if(n_read == -1){//等于-1 表示读取错误
perror("read");
}else if(n_read>0){//大于0 表示读到数据 并打印出来
printf("\nget: %d\n",n_read);
}else{//其他的表示客户端退出
printf("client quit\n");
break;
}
}
break;
}
}
return 0;
}
#include
#include
#include
#include
#include
#include
#include
int main(int argc, char **argv)
{
int c_fd;//客户端描述符
int n_read;//读了多少字节
char readBuf[128];//收到的数据缓存
int tmp;//
char msg[128] = {0};//发送的数据缓存
struct sockaddr_in c_addr;//客户端的协议结构体
memset(&c_addr,0,sizeof(struct sockaddr_in));
if(argc != 3){
printf("param is not good\n");
exit(-1);
}
printf("%d\n",getpid());//打印当前进程的进程ID
//1. socket AF_INET为ipv4协议 SOCK_STREAM为面向连接的通信流,tcp协议,0是自动匹配对应协议
c_fd = socket(AF_INET, SOCK_STREAM, 0);
if(c_fd == -1){
perror("socket");
exit(-1);
}
c_addr.sin_family = AF_INET;//记录上面的协议族ipv4协议
c_addr.sin_port = htons(atoi(argv[2]));//将字符串端口号转为数字然后转为网络字符
inet_aton(argv[1],&c_addr.sin_addr);//将ip地址转为网络字符放到sin_addr里
//2.connect c_fd是socket描述符 &c_addr是存放socket信息的结构体 sizeof...是结构体的大小
if(connect(c_fd, (struct sockaddr *)&c_addr,sizeof(struct sockaddr)) == -1){
perror("connect");
exit(-1);
}
while(1){
if(fork()==0){//子线程
while(1){//不断获取来自键盘的消息并且发送出去
memset(msg,0,sizeof(msg));
printf("input: ");
gets(msg);//
write(c_fd,msg,strlen(msg));//向描述符发送msg消息
}
}
while(1){//
memset(readBuf,0,sizeof(readBuf));
n_read = read(c_fd, readBuf, 128);//接收描述符对应的socket消息,放到readbuf里,最大读128字节
if(n_read == -1){
perror("read");//等于-1 表示读取错误
}else{
printf("\nget:%s\n",readBuf);//大于0 表示读到数据 并打印出来
}
}
}
return 0;
}