linux下socket编程归纳记录
所需头文件:
#include<sys/types.h>
#include<sys/socket.h>
基础套接字:
返回值:
0表示成功
-1表示失败
errno记录错误代码
1:创建套接字
int socket(int domain, int type, int protocol)
参数描述:
domain:套接字域名
{
AF_UNIX:用于本地通信
AF_INET:IPv4,Internet协议(本例使用该域名做参考)
AF_INET6:IPv6,Internet协议
.
.
}
type:套接字类型
{
SOCK_STREAM:流式套接字,用于套接字之间流式I/O操作,需先建立连接。特点1是数据按照写入时顺序被读取方接收,保证传输正确性,因此提供可靠的数据传输;特点2是仅仅是简单将数据交给接收方。
SOCK_DGRAM:数据报套接字,用与无连接通信。数据传输并不严格,接收端不能知道是否丢失了数据。
}
protocaol:使用的协议
{
一般情况下为0,系统会自动选择适合的协议类型。
}
2:请求连接函数:
int connect(int sockfd, const struct sockaddr *servaddr,socklen_t addrlen)
参数描述:
sockfd:sokect生成的套接字
servaddr:客户端准备连接的服务器地址
addrlen:服务器地址的长度
3:绑定本地地址函数:
int bind(int sockfd,const struct sockaddr *myaddr,socklen_t addrlen)
参数描述:
sockfd:sokect生成的套接字
myaddr:分配给套接字sockfd的地址指针
addrlen:myaddr地址的长度
4:监听函数:
int listen(int sockfd,int backlog)
参数描述:
sockfd:sokect生成的套接字
backlog:指完成TCP三次握手后已成功建立的TCP连接的队列长度,服务器执行accept操作从该队列中取下一个连接进行后续处理。
![backlog队列管理](http://img.blog.csdn.net/20150603105753422)
接收请求函数:
int accept(int sockfd, struct sockaddr *cliaddr,socklen_t *addrlen)
参数描述:
sockfd:sokect生成的套接字
cliaddr:用于接收客户端套接字地址的地址结构指针
addrlen:用于接收的套接字地址换岑最大长度的指针
返回值:
如果调用成功,将是一个新的套接字描述符,称为连接套接字,服务器使用该套接字和已建立连接的客户端进行通信,而原有的监听套接字继续接收后续新客户端发来的连接请求。连接套接字在通信完毕后通常会被立刻关闭,但是监听套接字一直处于监听状态直达应用结束。
例子
客户端:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main(void)
{
int st = socket(AF_INET, SOCK_STREAM, 0);//初始化socket,
struct sockaddr_in addr;//定义一个IP地址的结构
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;//设置结构地址类型为TCP/IP地址
addr.sin_port = htons(8080);//指定一个端口号:8080,htons:将short类型从host字节类型到net字节类型转化
addr.sin_addr.s_addr = inet_addr("192.168.182.128");//将字符串类型的IP地址转化为int,赋给addr结构成员.
//调用connect连接到结构addr指定的IP地址和端口号
if (connect(st, (struct sockaddr *) &addr, sizeof(addr)) == -1)
{
printf("connect failed %s\n", strerror(errno));
return EXIT_FAILURE;
}
char s[1024];
memset(s, 0, sizeof(1024));
strcpy(s, "hello world");
if (send(st, s, strlen(s), 0) == -1)//发送buf的数据
{
printf("send failed %s\n", strerror(errno));
return EXIT_FAILURE;
}
close(st);//关闭socket
return EXIT_SUCCESS;
}
服务器端:
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main(int arg, char *args[])
{
int st = socket(AF_INET, SOCK_STREAM, 0);//初始化socket
int on = 1;
if (setsockopt(st, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1)
{
printf("setsockopt failed %s\n", strerror(errno));
return EXIT_FAILURE;
}
struct sockaddr_in addr;//定义一个IP地址结构
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;//将addr结构的属性定位为TCP/IP地址
addr.sin_port = htons(8080);//将本地字节顺序转化为网络字节顺序。
addr.sin_addr.s_addr = htonl(INADDR_ANY);//INADDR_ANY代表这个server上所有的地址
//将IP与server程序绑定
if (bind(st, (struct sockaddr *) &addr, sizeof(addr)) == -1)
{
printf("bind failed %s\n", strerror(errno));
return EXIT_FAILURE;
}
//server端开始listen,
if (listen(st, 20) == -1)
{
printf("listen failed %s\n", strerror(errno));
return EXIT_FAILURE;
}
char s[1024];
int client_st = 0;//client端socket
//socklen_t len = 0;
struct sockaddr_in client_addr;//表示client端的IP地址
//void *p = &client_addr;
int i;
for (i = 0; i < 5; i++)
{
memset(&client_addr, 0, sizeof(client_addr));
socklen_t len = sizeof(client_addr);
//accept会阻塞,直到有客户端连接过来,accept返回client的socket描述符
client_st = accept(st, (struct sockaddr *)&client_addr , &len);
if (client_st == -1)
{
printf("accept failed %s\n", strerror(errno));
return EXIT_FAILURE;
}
while(1)
{
memset(s, 0, sizeof(1024));
int rc = recv(client_st, s, sizeof(s), 0);//recv是阻塞调用,
if (rc > 0)//接收来自client的消息
{
printf("revc is %s\n", s);
}else
{
if (rc == 0)
{
printf("client socket closed\n");
}else
printf("recv failed %s\n", strerror(errno));
break;
}
}
close(client_st);//关闭client端socket
}
close(st);//关闭server端listen的socket
return EXIT_SUCCESS;
}
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。