Posted on 2007-12-01 00:22
張旭 閱讀(633)
評(píng)論(0) 編輯 收藏 引用
今天重新把socket編程中的每一個(gè)函數(shù)的功能和說明都仔細(xì)的看了一遍,也有了更深一層的理解。在經(jīng)歷一次面試的失利之后,我覺得最大的問題就出在沒有對(duì)學(xué)過的知識(shí)力求甚解,導(dǎo)致對(duì)概念不清楚。所以在看這部分知識(shí)的時(shí)候,倍加用心的研究。
socket編程中主要用到一個(gè)結(jié)構(gòu) sockaddr和以下幾個(gè)函數(shù),socket(),bind(),connect(),listen(),accept(),send(),recv()。
bind函數(shù)是使用listen函數(shù)的必要條件,如果只需要connect的話,bind是不需要的。bind的作用是將套接字和機(jī)器的端口聯(lián)系起來。
connect()是建立兩臺(tái)電腦連接的必要函數(shù),首先要有一個(gè)已經(jīng)建立好的socket套接字,還有你要連接的目標(biāo)主機(jī)的ip地址以及端口號(hào)等信息。
accept(),當(dāng)connect的時(shí)候,主機(jī)需要通過accept來接受本次連接,accept需要對(duì)套接字進(jìn)行bind()。當(dāng)accept成功之后,函數(shù)會(huì)返回一個(gè)新的套接字描述符,通過新的描述符可以真對(duì)新的套接字進(jìn)行send和recv操作。
listen()是對(duì)端口的監(jiān)聽,你可以設(shè)定一個(gè)列隊(duì)的數(shù)量上線,這樣,在多個(gè)訪問請(qǐng)求到達(dá)的時(shí)候,可以排成隊(duì)伍,超過列隊(duì)上限的訪問將被拒絕。
簡(jiǎn)單的服務(wù)器
這個(gè)服務(wù)器所做的全部工作是在流式連接上發(fā)送字符串 "Hello, World!\n"。你要測(cè)試這個(gè)程序的話,可以在一臺(tái)機(jī)器上運(yùn)行該程序,然后 在另外一機(jī)器上登陸:
$ telnet remotehostname 3490
remotehostname 是該程序運(yùn)行的機(jī)器的名字。
服務(wù)器代碼:
1
#include <stdio.h>
2
#include <stdlib.h>
3
#include <errno.h>
4
#include <string.h>
5
#include <sys/types.h>
6
#include <netinet/in.h>
7
#include <sys/socket.h>
8
#include <sys/wait.h>
9
#define MYPORT 3490 /*定義用戶連接端口*/
10
#define BACKLOG 10 /*多少等待連接控制*/
11
main()
12
{
13
int sockfd, new_fd; /**//* listen on sock_fd, new connection on new_fd
14
*/
15
struct sockaddr_in my_addr; /**//* my address information */
16
struct sockaddr_in their_addr; /**//* connector's address information */
17
int sin_size;
18
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
19
perror("socket");
20
exit(1);
21
}
22
23
my_addr.sin_family = AF_INET; /**//* host byte order */
24
my_addr.sin_port = htons(MYPORT); /**//* short, network byte order */
25
my_addr.sin_addr.s_addr = INADDR_ANY; /**//* auto-fill with my IP */
26
bzero(&(my_addr.sin_zero),; /**//* zero the rest of the struct */
27
28
if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct
29
sockaddr))== -1)
{
30
perror("bind");
31
exit(1);
32
}
33
if (listen(sockfd, BACKLOG) == -1)
{
34
perror("listen");
35
exit(1);
36
}
37
38
while(1)
{ /**//* main accept() loop */
39
sin_size = sizeof(struct sockaddr_in);
40
if ((new_fd = accept(sockfd, (struct sockaddr *)&their_addr, \
41
&sin_size)) == -1)
{
42
perror("accept");
43
continue;
44
}
45
printf("server: got connection from %s\n", \
46
inet_ntoa(their_addr.sin_addr));
47
if (!fork())
{ /**//* this is the child process */
48
if (send(new_fd, "Hello, world!\n", 14, 0) == -1)
49
perror("send");
50
close(new_fd);
51
exit(0);
52
}
53
close(new_fd); /**//* parent doesn't need this */
54
while(waitpid(-1,NULL,WNOHANG) > 0); /**//* clean up child processes */
55
}
56
}
57
58
簡(jiǎn)單的客戶程序
這個(gè)程序比服務(wù)器還簡(jiǎn)單。這個(gè)程序的所有工作是通過 3490 端口連接到命令行中指定的主機(jī),然后得到服務(wù)器發(fā)送的字符串。
客戶代碼:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/wait.h>
#define PORT 3490 /* 客戶機(jī)連接遠(yuǎn)程主機(jī)的端口 */
#define MAXDATASIZE 100 /* 每次可以接收的最大字節(jié) */
int main(int argc, char *argv[])

{
int sockfd, numbytes;
char buf[MAXDATASIZE];
struct hostent *he;

struct sockaddr_in their_addr; /**//* connector's address information */

if (argc != 2)
{
fprintf(stderr,"usage: client hostname\n");
exit(1);
}

if ((he=gethostbyname(argv[1])) == NULL)
{ /**//* get the host info */
herror("gethostbyname");
exit(1);
}


if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
perror("socket");
exit(1);
}


their_addr.sin_family = AF_INET; /**//* host byte order */

their_addr.sin_port = htons(PORT); /**//* short, network byte order */
their_addr.sin_addr = *((struct in_addr *)he->h_addr);

bzero(&(their_addr.sin_zero),; /**//* zero the rest of the struct */
if (connect(sockfd, (struct sockaddr *)&their_addr,sizeof(struct

sockaddr)) == -1)
{
perror("connect");
exit(1);
}

if ((numbytes=recv(sockfd, buf, MAXDATASIZE, 0)) == -1)
{
perror("recv");
exit(1);
}
buf[numbytes] = '\0';
printf("Received: %s",buf);
close(sockfd);
return 0;
}

