struct sockaddr_in 在include/linux/in.h中
struct sockaddr_in {
sa_family_t sin_family; //地址家族,“AF_XXX”,AF_INET,代表TCP/IP协议族
__be16 sin_port; //存储端口号(使用网络字节顺序)
struct in_addr sin_addr;//存储IP地址
/* Pad to size of `struct sockaddr'. */
unsigned char __pad[__SOCK_SIZE__ - sizeof(short int) -
sizeof(unsigned short int) - sizeof(struct in_addr)];
};
include/linux/inet.h
#define INET_ADDRSTRLEN (16)
/* Address to accept any incoming messages. */
#define INADDR_ANY ((unsigned long int) 0x00000000)
sockaddr_in中的成员struct in_addr sin_addr表示32位的IP地址,但是我们通常用点分十进制字符串表示IP地址,以下函数可以在字符串表示和in_addr表示之间转换
字符串转in_addr的函数
#include <arpa/inet.h>
int inet_aton(const char *cp, struct in_addr *inp);
in_addr_t inet_addr(const char *cp);
in_addr转字符串函数
#include <arpa/inet.h>
const char *inet_ntop(int af, const void *src, char *dst, socklen_t size);
printf("received from [%s] at PORT [%d] \n", inet_ntop(AF_INET,&cliaddr.sin_addr, str, sizeof(str)), ntohs(cliaddr.sin_port));
/** *TCP server *从客户端读字符,然后将每个字符转换为大写并回送给客户端 */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/socket.h> #include <netinet/in.h> #define MAXLINE 80 #define SERV_PORT 8000 int main(void) { struct sockaddr_in servaddr, cliaddr; socklen_t cliaddr_len; int listenfd, connfd; char buf[MAXLINE]; char str[INET_ADDRSTRLEN]; int i, n; /** *socket()打开一个网络通讯端口,成功则返回一个文件描述符 *@AF_INET:IPv4 family参数指定为AF_INET *@SOCK_STREAM: TCP协议为SOCK_STREAM,UDP协议为SOCK_DGRAM *@0:表示IP */ listenfd = socket(AF_INET, SOCK_STREAM, 0); bzero(&servaddr, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl(INADDR_ANY);//宏INADDR_ANY表示本地的任意IP地址 servaddr.sin_port = htons(SERV_PORT); /** *bind()绑定一个固定的网络地址和端口号,成功返回0,失败返回-1 *listenfd这个用于网络通讯的文件描述符监听servaddr所描述的地址和端口 */ bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr)); /** *listen()声明listenfd处理监听状态,多个客户端发起连接,最多允许 *20个客户端处于连接待状态,如果接收到更多的连接请求就忽略 */ listen(listenfd, 20); printf("Accepting connections ...\n"); //while死循环,每次循环处理一个客户端连接 //cliaddr是传入传出参数,每次调用accept()之前应该重新赋值 while (1) { cliaddr_len = sizeof(cliaddr); /** *三次握手后,服务器调用accept()接受连接 *如果服务咕咕调用accept()时还没有客户端的连接请求 *就阻塞等待直到有客户端连接 *@cliaddr:传出参数,accept()返回时传出客户端的地址和端口号 *如果cliaddr参数为NULL,表示不关心客户端的地址 */ connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &cliaddr_len); n = read(connfd, buf, MAXLINE); printf("received from [%s] at PORT [%d] \n", inet_ntoa(cliaddr.sin_addr), ntohs(cliaddr.sin_port)); printf("%s \n", buf); for (i = 0; i< n; i++) buf[i] = toupper(buf[i]); write(connfd, buf, n); close(connfd); } }
/** *client TCP *从命令行参数中获得一个字符串发给服务器,然后接收服务器 *返回的字符串并打印 */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/socket.h> #include <netinet/in.h> #define MAXLINE 80 #define SERV_PORT 8000 int main(int argc, char **argv) { struct sockaddr_in servaddr; char buf[MAXLINE]; int sockfd, n; char *str; if (argc != 2) { fputs("usage: ./client message\n", stderr); exit(1); } str = argv[1]; /** *客户端不需要固定的端口号,因此不调用bind() */ sockfd = socket(AF_INET, SOCK_STREAM, 0); bzero(&servaddr, sizeof(servaddr)); servaddr.sin_family = AF_INET; inet_pton(AF_INET, "10.50.25.10", &servaddr.sin_addr); servaddr.sin_port = htons(SERV_PORT); /** *客户端需要connect()连接服务器 *@servaddr:是服务器的地址 */ connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)); write(sockfd, str, strlen(str)); n = read(sockfd, buf, MAXLINE); printf("Response from server:\n"); write(STDOUT_FILENO, buf, n); printf("\n"); close(sockfd); return 0; }