Linux C Socket简单应用
简单的socket应用。
server代码
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define PORT 33333
int main()
{
int sockfd;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd == -1){
perror("socket create failed!");
exit(1);
}
int opt = 1;
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof (opt));
struct sockaddr_in addr;
bzero(&addr, sizeof (struct sockaddr_in));
addr.sin_family = AF_INET;
addr.sin_port = htons(PORT);
addr.sin_addr.s_addr = inet_addr("192.168.43.106"); //自己主机IP
if(bind(sockfd, (struct sockaddr*)(&addr), sizeof (struct sockaddr_in)) < 0){
perror("bind failed!");
exit(1);
}
if(listen(sockfd, 3) < 0){
perror("listen failed!");
exit(1);
}
printf("listen successful\n");
char buffer[1024];
while (1) {
memset(buffer, 0, sizeof(buffer));
struct sockaddr_in c_addr;
socklen_t c_len = sizeof (struct sockaddr_in);
int cfd;
bzero(&c_addr, sizeof (struct sockaddr_in));
cfd = accept(sockfd, (struct sockaddr*)(&c_addr), &c_len);
if(cfd == -1){
perror("accept failed");
exit(1);
}
printf("accept successful\n");
printf("port = %d, ip = %s\n", ntohs(c_addr.sin_port), inet_ntoa(c_addr.sin_addr));
recv(cfd, buffer, sizeof(buffer), 0);
printf("re: %s \n", buffer);
send(cfd, buffer, sizeof(buffer), 0);
}
return 0;
}
client端代码
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define PORT 33333
int main()
{
int sockfd;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd == -1){
perror("socket create failed!");
exit(1);
}
struct sockaddr_in s_addr;
bzero(&s_addr, sizeof (struct sockaddr_in));
s_addr.sin_family = AF_INET;
s_addr.sin_port = htons(PORT);
s_addr.sin_addr.s_addr = inet_addr("192.168.43.106");
if(connect(sockfd, (struct sockaddr*)(&s_addr), sizeof (struct sockaddr_in)) < 0){
perror("connect failed!");
exit(1);
}
char* message = "hello";
send(sockfd, message, 5, 0);
char buf[1024];
recv(sockfd, buf, sizeof(buf), 0);
printf("%s\n", buf);
return 0;
}
1. socket函数
NAME
socket - create an endpoint for communication
SYNOPSIS
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
int socket(int domain, int type, int protocol);
socket()函数创建一个socket并且返回一个对应的描述符。
其参数分别为:
Address Family - AF_INET => IPv4
Type - SOCK_STREAM => socket连接使用TCP协议
Protocol - 0 => 使用IP协议
2. setsockopt,setsockopt函数
NAME
getsockopt, setsockopt - get and set options on sockets
SYNOPSIS
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
int getsockopt(int sockfd, int level, int optname,
void *optval, socklen_t *optlen);
int setsockopt(int sockfd, int level, int optname,
const void *optval, socklen_t optlen);
该函数用于获取或者设置与某个套接字关联的选 项
参数:
sockfd:将要被设置或者获取选项的套接字。
level:选项所在的协议层。
optname:需要访问的选项名。
optlen:对于getsockopt(),指向返回选项值的缓冲。对于setsockopt(),指向包含新选项值的缓冲。
optlen:对于getsockopt(),作为入口参数时,选项值的最大长度。作为出口参数时,选项值的实际长度。对于setsockopt(),现选项的长度。
level指定控制套接字的层次.可以取三种值:
1)SOL_SOCKET:通用套接字选项。
2)IPPROTO_IP:IP选项。
3)IPPROTO_TCP:TCP选项。
optname指定控制的方式
SO_REUSERADDR 允许重用本地地址和端口 int
3. bind函数
NAME
bind - bind a name to a socket
SYNOPSIS
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
int bind(int sockfd, const struct sockaddr *addr,
socklen_t addrlen);
bind()函数可以将socket绑定到一个端口上,client可以通过向这个端口发起请求,端口对应的socket便会与client端的socket连接。
4. listen函数
NAME
listen - listen for connections on a socket
SYNOPSIS
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
int listen(int sockfd, int backlog);
listen => 可以将socket处于监听的状态。
其参数为:
sockfd => 设置监听的socket。
backlog => 在当前连接后面允许存在的最大未处理连接数。
5. accept函数
NAME
accept, accept4 - accept a connection on a socket
SYNOPSIS
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
#define _GNU_SOURCE /* See feature_test_macros(7) */
#include <sys/socket.h>
int accept4(int sockfd, struct sockaddr *addr,
socklen_t *addrlen, int flags)
accept函数的作用就是接收请求。
参数:
sockfd => socket的描述符
addr =>IP地址结构体,该参数是一个传出参数,我们传入一个空的addr进入,将返回客户端的IP地址数据。
addrlen =>IP地址结构体长度。
该函数的返回值是客户端的sockfd,后续对该客户端进行双向通信需要用到该sockfd返回值。
7. connect函数
NAME
connect - initiate a connection on a socket
SYNOPSIS
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
int connect(int sockfd, const struct sockaddr *addr,
socklen_t addrlen);
connect()函数会向服务器发起请求建立一个连接。
其参数为:
sockfd => socket的描述符
addr => sockaddr的结构体,通用的socket地址
addrlen => socket描述符的长度。
8. recv函数
NAME
recv, recvfrom, recvmsg - receive a message from a socket
SYNOPSIS
#include <sys/types.h>
#include <sys/socket.h>
ssize_t recv(int sockfd, void *buf, size_t len, int flags);
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
struct sockaddr *src_addr, socklen_t *addrlen);
ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags);
recv函数用于接受数据,参数很简单。
sockfd 套接字
buf 缓冲区
len 缓冲区长度
flags 标志,一般为0
9. send函数
NAME
send, sendto, sendmsg - send a message on a socket
SYNOPSIS
#include <sys/types.h>
#include <sys/socket.h>
ssize_t send(int sockfd, const void *buf, size_t len, int flags);
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
const struct sockaddr *dest_addr, socklen_t addrlen);
ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags);
send函数用于发送数据,参数同revc函数。