linux学习笔记17-网络通信socket-tcp
套接字(socket)
socket是跨平台的,可以用在系统间通信(windows/linux/Android/ios等),也可以用在进程间通信,常用socket类型,分为tcp(流式SOCK_STREAM)和udp(数据报文SOCK_DGRAM).概念性的先不讲,先看看在Linux怎么使用吧.client(tcp客户端实现)
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
int main(int argc,char *argv[])
{
if(argc < 3) //接收3个参数,分别为./sock(程序名) 127.0.0.1(ip地址) 8081(端口号)
{
printf("argc < 3\n");
return -1;
}
int port = atoi(argv[2]);
int sock = socket(AF_INET,SOCK_STREAM,0); //初始化socket
struct sockaddr_in addr; //ip地址结构
memset(&addr,0,sizeof(addr)); //初始化ip结构
addr.sin_family = AF_INET; //设置结构类型类tcp/ip地址
addr.sin_port = htons(port); //指定一个端口号, htons将short类型从host字节类型换net字节类型
addr.sin_addr.s_addr = inet_addr(argv[1]); //将ip地址转为int类型数据,赋值给s_addr
if(connect(sock,(struct sockaddr *)&addr,sizeof(addr)) == -1)
{
printf("connect failed:%s\n",strerror(errno));
return -1;
}
char buf[1024] = {0};
while(1)
{
read(STDIN_FILENO,buf,sizeof(buf)); //等待输入内容
if(send(sock,buf,strlen(buf),0) == -1) //将内容发送
{
printf("send failed:%s\n",strerror(errno));
return -1;
}
memset(buf,0,sizeof(buf)); //将字符数组清空
if(recv(sock,buf,sizeof(buf),0)>0) //接收服务端发送的内容
{
printf("server msg:%s",buf);
}
else
{
break; //接收内容不大于0,退出循环
}
}
close(sock); //使用完毕,关闭socket
return 0;
}
server(tcp服务端实现)
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main(int argc,char *argv[])
{
if(argc <2 ) //接收2个参数 第2个参数为服务端监听端口号
{
printf("argc < 2!\n");
return -1;
}
int port = atoi(argv[1]);
int sock = socket(AF_INET,SOCK_STREAM,0); //初始化socket
int on = 1;
if(setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on)) == -1) //设置socket经历TIME_WAIT后重用socket
{
printf("setscoket failed:%s\n",strerror(errno));
return -1;
}
struct sockaddr_in addr; //ip地址结构
memset(&addr,0,sizeof(addr)); //初始化ip结构
addr.sin_family = AF_INET; //设置结构类型类tcp/ip地址
addr.sin_port = htons(port); //指定一个端口号, htons将short类型从host字节类型换net字节类型 ,将本地字节顺序转换为网络字节顺序
addr.sin_addr.s_addr = htonl(INADDR_ANY); //服务器的所有地址
if(bind(sock,(struct sockaddr *)&addr,sizeof(addr)) == -1) //将ip与server程序绑定
{
printf("bind failed:%s\n",strerror(errno));
return -1;
}
if(listen(sock,20) == -1) //开始监听
{
printf("listen failed:%s\n",strerror(errno));
return -1;
}
char buf[1024];
int client_sock = 0;
struct sockaddr_in client_addr; //表示client的ip地址
void *p = &client_addr;
while(1)
{
memset(&client_addr,0,sizeof(client_addr));
int len = sizeof(client_addr);
client_sock = accept(sock,p,&len); //accept会阻塞,直到客户端连接过来,返回client的socket描述符
if(client_sock == -1)
{
printf("accept failed:%s\n",strerror(errno));
return -1;
}
printf("accept ip:%s\n",inet_ntoa(client_addr.sin_addr));
while(1)
{
memset(buf,0,sizeof(buf));
int recv_result = recv(client_sock,buf,sizeof(buf),0); //recv也是阻塞的
if(recv_result < 0) //发生错误时
{
printf("recv failed:%s\n",strerror(errno));
close(client_sock);
return -1;
}
else if(recv_result == 0) //连接时,为空
{
printf("server content:%s\n",strerror(errno));
break;
}
else
{
printf("server content:%s",buf);
memset(buf,0,sizeof(buf)); //清空字符串
read(STDIN_FILENO,buf,sizeof(buf)); //等待输入内容
send(client_sock,buf,sizeof(buf),0); //将输入的内容发送过去
}
}
close(client_sock); //使用完毕,一定要关闭
}
close(sock);
return 0;
}
效果展示

秋风
2016-12-03