socket实现客户端与服务端之间的Tcp通信
程序员文章站
2022-06-06 16:08:31
...
TCP通信流程分析:
server:
1. socket(int socket_family, int socket_type, int protocol) 创建socket,返回用于监听的套接字
2. bind(int sockfd, const struct sockaddr *my_addr, socklen_t addrlen) 绑定服务器地址结构(IP+port)
3. listen(fd, 128) 设置监听上限
4. accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)阻塞监听客户端连接,sockfd为socket函数返回值,返回新的已经成功与客户端连接的的文件描述符
5. ssize_t read(int fd,void *buf, size_t count) 读socket获取客户端数据
6. 小写转大写 toupper()
7. ssize_t write(int fd, const void *buf, size_t count) //向缓冲区写入数据
8. close();
client:
1. socket() 创建socket
2. int connect(int socketfd, const struct sockaddr *addr, socklen_t addrlen); 与服务器建立连接
3. write() 写数据到 socket
4. read() 读转换后的数据。
5. 显示读取结果
6. close()
相关函数及参数说明
htonl() 本地字节序转网络字节序(IP)
htons() 本地字节序转网络字节序(port)
ntohl() 网络字节序转本地字节序(IP)
ntohs() 网络字节序转本地字节序(port)
//点分十进制IP地址转换为网络字节序
int inet_pton(int af, const void *src, char *dst, socklen_t size);
//网络字节序转点分十进制IP地址
const char *inet_ntop(int af, const void *src, char *dst, socklen_t size);
sockaddr_in地址结构:
struct sockaddr_in {
sa_family_t sin_family; /* 地址族: AF_INET */
u_int16_t sin_port; /* 按网络字节次序的端口 */
struct in_addr sin_addr; /* internet地址 */
};
/* Internet地址. */
struct in_addr {
u_int32_t s_addr; /* 按网络字节次序的地址 */
};
sockaddr_in初始化:
struct sockaddr_in addr;
addr.sin_family = AF_INET/AF_INET6; //IPv4或IPv6
addr.sin_port = htons(9527); //将本地字节序转为short类型的网络字节序
//方法一,实际一般不这么用
int dst;
inet_pton(AF_INET, "192.127.22.45",(void *)dst);
addr.sin_addr.s_addr = dst;
//方法二
addr.sin_addr.s_addr = htonl(INADDR_ANY);//取出系统中有效的任意IP地址。
在实际作为accept、connect函数的参数使用时还要将sockaddr_in强转为sockaddr类型
服务端
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <unistd.h>
#include <ctype.h>
#include <sys/socket.h>
#include <errno.h>
#include <pthread.h>
#include <string.h>
#define SERV_PORT 9528
void sys_err(const char *str)
{
perror(str);
exit(1);
}
int main(int argc, char *argv[])
{
int lfd, cfd;//监听文件描述符,client文件描述符
char buf[BUFSIZ], client_IP[1024];
int i;
struct sockaddr_in serv_addr, clit_addr;
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(SERV_PORT);
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
lfd = socket(AF_INET, SOCK_STREAM, 0);
if(lfd == -1) sys_err("socket error");
int ret = bind(lfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr));
if(ret == -1) sys_err("bind error");
ret = listen(lfd, 128);
if(ret == -1) sys_err("listen error");
socklen_t clit_addr_len = sizeof(clit_addr);
cfd = accept(lfd, (struct sockaddr *)&clit_addr, &clit_addr_len);
if(cfd == -1) sys_err("accept error");
printf("client IP:%s, port:%d\n",
inet_ntop(AF_INET, &clit_addr.sin_addr.s_addr, client_IP, sizeof(client_IP)),
ntohs(clit_addr.sin_port));
while(1)
{
ssize_t readsize = read(cfd, buf, sizeof(buf));
for(i=0; i<readsize; i++)
buf[i] = toupper(buf[i]);
write(cfd, buf, readsize);
}
close(lfd);
close(cfd);
return 0;
}
客户端
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <pthread.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <ctype.h>
#define SERV_PORT 9528
void sys_err(const char *str)
{
perror(str);
exit(1);
}
int main(int argc, char *argv[])
{
int cfd;
int counter = 10;
char buf[BUFSIZ];
struct sockaddr_in serv_addr; //服务器地址结构
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(SERV_PORT);
inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr.s_addr);
//serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
cfd = socket(AF_INET, SOCK_STREAM, 0);
if(cfd == -1) sys_err("socket error");
int ret = connect(cfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr));
if(ret != 0) sys_err("connect error");
while(--counter)
{
write(cfd, "hello\n", sizeof("hello\n"));
ret = read(cfd, buf, sizeof(buf));
write(STDOUT_FILENO, buf, ret);
sleep(1);
}
close(cfd);
return 0;
}
上一篇: Java swing读取txt文件实现学生考试系统
下一篇: 五招预防脸上长冻疮 保湿防晒至关重要