#include
#include
int socket(int domain, int type, int protocol);
//-domain: 指定通信域(通信地址族);
//-type: 指定套接字类型;
//-protocol: 指定协议;
参数:
套接字类型与协议
-type: 指定套接字类型
TCP唯一对应流式套接字,所以选择SOCK_STREAM(数据报套接字:SOCK_DGRAM)
-protocol: 指定协议
流式套接字唯一对应TCP,所以无需要指定协议,设为0即可
#include
#include
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
//-sockfd:socket函数生成的套接字
//-addr:通信结构体
//-addrlen:通信结构体的长度
//IPV4地址族结构体
struct sockaddr_in {
sa_family_t sin_family; /* 地址族: AF_INET */
in_port_t sin_port; /* 网络字节序的端口号 */
struct in_addr sin_addr; /*IP地址结构体 */
};
/* IP地址结构体 */
struct in_addr {
uint32_t s_addr; /* 网络字节序的IP地址 */
};
//通用地址族结构体
struct sockaddr {
sa_family_t sa_family;
char sa_data[14];
}
//实例:为套接字fd绑定通信结构体addr
addr.sin_family = AF_INET;
addr.sin_port = htons(5001);//主机字节序转网络字节序,16位数据
addr.sin_addr.s_addr = 0;
bind(fd, (struct sockaddr *)&addr, sizeof(addr) );
/*监听套接字*/
int listen(int sockfd, int backlog);
/*处理客户端发起的连接,生成新的套接字*/
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
-sockfd: 函数socket生成的套接字
-addr(传出参数):客户端的地址族信息
-addrlen:地址族结构体的长度
注意:accept()函数是一个阻塞函数。
作业:实现TCP通信代码,并用Makefile进行编译
服务器端:
//server.c //服务器端
#include
#include
#include
#include
#include
#include
#include
#define BACKLOG 5
int main(int argc, char *argv[])
{
int fd, newfd, ret;
char buf[BUFSIZ] = {}; //BUFSIZ 8142
struct sockaddr_in addr;
if(argc < 3){
fprintf(stderr, "%s\n", argv[0]);
exit(0);
}
/*创建套接字*/
fd = socket(AF_INET, SOCK_STREAM, 0);//fd是监听文件描述符
if(fd < 0){
perror("socket");
exit(0);
}
addr.sin_family = AF_INET;
addr.sin_port = htons( atoi(argv[2]) );
if ( inet_aton(argv[1], &addr.sin_addr) == 0) {
fprintf(stderr, "Invalid address\n");
exit(EXIT_FAILURE);
}
/*绑定通信结构体*/
if(bind(fd, (struct sockaddr *)&addr, sizeof(addr) ) == -1){
perror("bind");
exit(0);
}
/*设置套接字为监听模式*/
if(listen(fd, BACKLOG) == -1){
perror("listen");
exit(0);
}
/*接受客户端的连接请求,生成新的用于和客户端通信的套接字*/
newfd = accept(fd, NULL, NULL);//newfd是通信文件描述符
if(newfd < 0){
perror("accept");
exit(0);
}
while(1){
memset(buf, 0, BUFSIZ);
ret = read(newfd, buf, BUFSIZ);
if(ret < 0)
{
perror("read");
exit(0);
}
else if(ret == 0)
break;
else
printf("buf = %s\n", buf);
}
close(newfd);
close(fd);
return 0;
}
客户端:
//client.c //客户端
#include
#include
#include
#include
#include
#include
#include
#define BACKLOG 5
int main(int argc, char *argv[])
{
int fd;
struct sockaddr_in addr;
char buf[BUFSIZ] = {};
if(argc < 3){
fprintf(stderr, "%s\n", argv[0]);
exit(0);
}
/*创建套接字*/
fd = socket(AF_INET, SOCK_STREAM, 0);//fd是通信文件描述符
if(fd < 0){
perror("socket");
exit(0);
}
addr.sin_family = AF_INET;
addr.sin_port = htons( atoi(argv[2]) );
if ( inet_aton(argv[1], &addr.sin_addr) == 0) {
fprintf(stderr, "Invalid address\n");
exit(EXIT_FAILURE);
}
/*向服务端发起连接请求*/
if(connect(fd, (struct sockaddr *)&addr, sizeof(addr) ) == -1){
perror("connect");
exit(0);
}
while(1){
printf("Input->");
fgets(buf, BUFSIZ, stdin);
write(fd, buf, strlen(buf) );
}
close(fd);
return 0;
}
Makefile:
CC=gcc
CFLAGS=-Wall
all:client server
clean:
rm client server