Socket套接字编程🐣
由于套接字编程是很庞大的,本文作为学习笔记也仅仅实现了较为简单和基础的部分,但是希望对大家有帮助
所有计算机网络学习笔记链接
//IP socket address structure
//sockaddr_in: 因特网套接字地址
struct sockaddr_in {
uint_16_t sin_family; //协议族
uint_16_t sin_port; //端口
struct in_addr sin_addr; //32位的IP地址
unsigned char sin_zero[8]; //sizeof (struct sockaddr)
}
//用于:connect, bind, accept
struct sockaddr {
uint16_t safamily;
char sa_data[14];
}
socke函数讲解
cocket
#include <sys/types.h>
#include <sys/socket.h>
int socket(int domain, int type, int protocol)
#成功返回非负描述符号, 出错返回-1
#实例
clientfd = socket(SF_INET, SOCK_STREAM, 0); //default : 0
bind
#include <sys/socket.h>
int bind(int sockfd, const struct sockaddr * addr, socklen_t addrlen);
#成功返回0 出错返回 -1
listen
#include <sys/socket.h>
int listen(int sockfd, int backlog);
#成功就返回0 否则就返回 -1
accept
#include <sys/socket.h>
int accept(int listenfd, struct sockaddr * addr, int * addrlen);
#成功就返回 非负连接描述符号,出错就返回 -1
#read用于读取数据
ssize_t read (int fd, void * buf, size_t count);
#write 用于写数据, 同样也是阻塞式的
ssize_t write(int fd, const void * buf, size_t count);
int connect (int clientfd, const struct sockaddr * addr, socklen_t addrlen);
主机字节序和网络字节序相互转换
uint32_t htonl(uint32_t hostlong); //32位主机转网络
uint16_t htons(uint16_t hostshort); //16位主机转网络
uint32_t ntohl(uint32_t netlong); //32位网络转主机
uint16_t ntohs(uint16_t netshort); //16位网络转主机
套接字案例
s e r v e r . c server.c server.c
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/shm.h>
const int MYPORT = 8887;
const int QUEUE = 20;
const int BUFFER_SIZE = 20;
/*
(2) struct sockaddr_in(IP专用的地址结构)
structsockaddr_in {
u_char sin_len;//长度
u_short sin_family;//协议
u_short sin_port;//端口
structin_addr sin_addr;//ip地址
char sin_zero[8];//数据
};
(3) struct in_addr
structin_addr {undefined
u_longs_addr;
};
*/
//Server_addr : 指明远程的IP地址和端口号码
int main()
{
//创建了套接字
int server_sockfd = socket(AF_INET, SOCK_STREAM, 0);
//定义sockaddr_in
struct sockaddr_in server_sockaddr;
server_sockaddr.sin_family = AF_INET;
server_sockaddr.sin_port = htons(MYPORT); //端口的转换函数
server_sockaddr.sin_addr.s_addr = htonl(INADDR_ANY); //IP地址
//bind 成功返回0,出错返回 -1
if (bind(server_sockfd, (struct sockaddr *) & server_sockaddr, sizeof(server_sockaddr)) == -1) {
perror("bind");
exit(1);
}
printf ("监听:%d端口\n", MYPORT);
//listen成功的话返回0 , 出错返回 -1
if (listen(server_sockfd, QUEUE) == -1) {
perror("listen");
exit(1);
}
//客户端套接字
char buffer[BUFFER_SIZE];
struct sockaddr_in client_addr; //用来标识客户端的结构体
socklen_t length = sizeof (client_addr);
printf("等待客户端连接\n");
//成功 -> 返回非负
//失败 -> 返回-1
int conn = accept(server_sockfd, (struct sockaddr*) & client_addr, & length);
if (conn < 0) {
perror("connect");
exit(1);
}
printf("客户端成功连接\n");
while (1) {
memset(buffer, 0, sizeof (buffer));
int len = recv(conn, buffer, sizeof (buffer), 0);
//客户端发送exit时候进行终止退出
if (strcmp (buffer, "exit\n") == 0 || len <= 0) {
break;
}
printf("来自客户端的数据:%s\n", buffer);
send(conn, buffer, len, 0);
printf("发送给客户端的数据:%s\n", buffer);
}
close(conn);
close(server_sockfd);
return 0;
}
c l i e n t . c client.c client.c
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/shm.h>
#define MYPORT 8887
#define BUFFER_SIZE 1024
char * SERVER_IP = "127.0.0.1";
int main()
{
//定义sockfd
int sock_cli = socket(AF_INET, SOCK_STREAM, 0);
//定义一下sockaddr_in
struct sockaddr_in servaddr;
memset(&servaddr, 0, sizeof (servaddr));
servaddr.sin_family = AF_INET; //定义协议族
servaddr.sin_port = htons(MYPORT);
servaddr.sin_addr.s_addr = inet_addr(SERVER_IP); //服务器IP
printf("连接%s: %d\n", SERVER_IP, MYPORT);
//连接服务器,成功返回0 错误返回-1
if (connect(sock_cli, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0) {
perror("connect\n");
exit(1);
}
printf("服务器连接成功!\n");
//建立了同服务器端新创建的套接字的连接
char sendbuf[BUFFER_SIZE];
char recvbuf[BUFFER_SIZE];
while (fgets(sendbuf, sizeof (sendbuf), stdin) != NULL ) {
printf("向服务器发送数据: %s\n", sendbuf);
send(sock_cli, sendbuf, strlen(sendbuf), 0);
if (strcmp(sendbuf,"exit\n") == 0) {
break; //输入exit就退出了
}
recv(sock_cli, recvbuf, sizeof(recvbuf), 0);
printf("从服务器接收数据:%s\n", recvbuf);
memset(sendbuf, 0, sizeof (sendbuf));
memset(recvbuf, 0, sizeof (recvbuf));
}
close(sock_cli);
return 0;
}
参考资料
https://blog.csdn.net/weixin_44164489/article/details/108606391
https://blog.csdn.net/chengqiuming/article/details/89298442