当我们调用socket创建一个socket时,返回的socket描述字它存在于协议族(address family,AF_XXX)空间中,但没有一个具体的地址。如果想要给它赋值一个地址,就必须调用bind()函数,否则就当调用connect()listen()时系统会自动随机分配一个端口。


通常服务器在启动的时候都会绑定一个众所周知的地址(如ip地址+端口号),用于提供服务,客户就可以通过它来接连服务器;而客户端就不用指定,有系统自动分配一个端口号和自身的ip地址组合。这就是为什么通常服务器端在listen之前会调用bind(),而客户端就不会调用,而是在connect()时由系统随机生成一个。


TCP服务器端依次调用socket()bind()listen()之后,就会监听指定的socket地址了。TCP客户端依次调用socket()connect()之后就想TCP服务器发送了一个连接请求。TCP服务器监听到这个请求之后,就会调用accept()函数取接收请求,这样连接就建立好了。之后就可以开始网络I/O操作了,即类同于普通文件的读写I/O操作。


client:

#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];
        sockfd = socket(AF_INET, SOCK_STREAM, 0);
        bzero(&servaddr, sizeof(servaddr));
        servaddr.sin_family = AF_INET;
        inet_pton(AF_INET, "127.0.0.1", &servaddr.sin_addr);
        servaddr.sin_port = htons(SERV_PORT);
        if (-1 == connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)))
                printf("connect to server return -1\n");
        write(sockfd, str, strlen(str));
        n = read(sockfd, buf, MAXLINE);
        printf("Response from server:\n");
        write(STDOUT_FILENO, buf, n);
        close(sockfd);
        return 0;
}


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;
        listenfd = socket(AF_INET, SOCK_STREAM, 0);            
        bzero(&servaddr, sizeof(servaddr));
        servaddr.sin_family = AF_INET;
        servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
        servaddr.sin_port = htons(SERV_PORT);
        bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
        listen(listenfd, 20);
        printf("Accepting connections ...\n");
        while (1) {
                cliaddr_len = sizeof(cliaddr);
                connfd = accept(listenfd,
                        (struct sockaddr *)&cliaddr, &cliaddr_len);
                n = read(connfd, buf, MAXLINE);
                printf("received from %s\n", buf);
                //printf("received from %s at PORT %d\n",
                //      inet_ntop(AF_INET, &cliaddr.sin_addr, str, sizeof(str)),
                //      ntohs(cliaddr.sin_port));
                for (i = 0; i < n; i++)
                        buf[i] = toupper(buf[i]);
                write(connfd, buf, n);
                close(connfd);
        }
}