最近一直在用linux,很早就想学习linux网络编程。
今天刚好抽出一段时间,学习了简单的socket通信,写了一个简单的客户端/服务器通信代码。现在将今天学习的内容做一个总结。
一、相关概念说明
Socket起源于Unix,而Unix基本哲学之一就是“一切皆文件”,都可以用“打开open –> 读写write/read –> 关闭close”模式来操作。Socket就是该模式的一个实现,网络的Socket数据传输是一种特殊的I/O,Socket也是一种文件描述符。Socket也具有一个类似于打开文件的函数调用:Socket(),该函数返回一个整型的Socket描述符,随后的连接建立、数据传输等操作都是通过该Socket实现的。(摘自网络https://github.com/astaxie/build-web-application-with-golang/blob/master/zh/08.1.md)
二、常用数据类型
struct sockaddr
{
sa_family_t sa_family;
char sa_data[14];
};
struct sockaddr_in
{
sa_family_t sin_family; //地址族: AF_INET
u_int16_t sin_port; //端口号:用网络字节序表示
struct in_addr sin_addr; //IPv4地址结构体
};
三、常用函数介绍
1.创建socket
int socket (int domain, int type, int protocol);
参数介绍:domain协议族、type指定服务类型、protocol在前两个参数构成的协议族集合下,选择一个具体的协议,一般为0。
2.命名socket
int bind (int fd, const struct sockaddr* addr, socklen_t len);
将socket和socket地址绑定到一起
参数介绍:fd句柄(文件描述符),addr协议(socket地址),len长度3.监听socket
int listen(int sockfd, int backlog);
参数介绍:backlog参数提示内核监听队列的最大长度,即可以最大连接数量。
4.接受连接
int accept (int fd, struct sockaddr* addr, socklen_t * addr_len);
需注意,这里的addr为一个新的socket地址,用于存放接受到的连接信息。
5.发起连接int connect (int fd, const struct sockaddr* addr, socklen_t len);
int close(int fd);
发送接收,读写
recv,send,read,write。
四、简单例子
客户端
#include
#include
#include
#include
#include
#include
#include
int main()
{
char buf[256] = "hello";
int recbytes = 0;
int i = 5;
struct sockaddr_in saddr;
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
if ( -1 == sockfd )
{
printf("socket failed!\n");
return -1;
}
printf("socket success!\n");
memset(&saddr, 0, sizeof(struct sockaddr_in));
saddr.sin_family = AF_INET;
saddr.sin_addr.s_addr = inet_addr("127.0.0.1");
saddr.sin_port = htons(5500);
if( -1 == connect(sockfd, (struct sockaddr *)(&saddr), sizeof(struct sockaddr)) )
{
printf("connect failed\n");
return -1;
}
printf("connect success!\n");
while(i)
{
// int res = send(sockfd, buf, 255, 0);
// if( -1 == res )
// {
// printf("send failed!\n");
// return -1;
// }
// printf("send success\n");
if( -1 == write(sockfd, "hello", 32))
{
printf("write failed\n");
return -1;
}
printf("write success\n");
i -= 1;
}
close(sockfd);
return 0;
}
服务端
#include
#include
#include
#include
#include
#include
#include
#include
int main()
{
int nfp;
char buf[256] = {0};
int recbytes = 0;
struct sockaddr_in saddr, caddr;
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
if ( -1 == sockfd )
{
printf("socket failed!\n");
return -1;
}
printf("socket success!\n");
memset(&saddr, 0, sizeof(struct sockaddr_in));
saddr.sin_family = AF_INET;
saddr.sin_addr.s_addr = inet_addr("127.0.0.1");
saddr.sin_port = htons(5500);
if( -1 == bind(sockfd, (struct sockaddr *)(&saddr), sizeof(struct sockaddr)))
{
printf("bind failed!\n");
return -1;
}
printf("bind success!\n");
if( -1 == listen(sockfd,5))
{
printf("listen failed!\n");
return -1;
}
printf("listen success!\n");
recbytes = sizeof(struct sockaddr_in);
nfp = accept(sockfd, (struct sockaddr *)(&caddr), &recbytes);
if( -1 == nfp )
{
printf("accept failed\n");
return -1;
}
printf("accept success\n");
while(1)
{
buf[0] = '\0';
// int res = recv(nfp, buf, 255, 0);
// if( -1 == res )
// {
// perror("");
// printf("recv error!\n");
// return -1;
// }
// if( 0 == res )
// {
// printf("recv ok!\n");
// return 0;
// }
// recbytes = strlen(buf);
// buf[recbytes] = '\0';
// printf("%s\n", buf);
//
recbytes = read(nfp, buf, 255);
if( -1 == recbytes )
{
printf("read data failed\n");
perror("");
return -1;
}
if( 0 == recbytes )
{
printf("read ok!\n");
return 0;
}
printf("read data success!\n");
buf[recbytes] = '\0';
printf("%s\n", buf);
}
getchar();
close(sockfd);
return 0;
}
如果有什么问题,可以联系我,共同学习。