1.int socket(int domain, int type, int protocol);
创建一个socket套接字,并返回一个套接字描述符
第一个参数用以选择套字的协议族
常用参数极其目的如下:
第二个参数用以选择套接字的传输方式,在TCP协议中我们选择SOCK_STREAM使我们的创建的套接字成为 一个有序的,可靠的,双向数据流。
第三个参数为0。
返回值>0为socket描述符,等于0说明创建socket错误。
void bzero(void *s, size_t n);
bzero()函数可以将前N个字节的信息设置为’\0’。
无返回值
参数:
*s ——想要的更改的数据
n ——想要更改数据的长度
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
功能:连接服务器
参数
sockfd——我们之前创建的套接字描述符
sockaddr的结构体,其内部定义如下:
struct sockaddr_in {
short sin_family /AF_INET/
u_short sin_port; /端口号,网络字节顺序/
struct in_addr sin_addr; /IP地址,网络字节顺序/
char sin_zero[8]; /填充字节,必须为全零/
};
我们可以在sockaddr中定义端口号,套接字类型,ip地址如下:
addrlen——地址结构长度
设置代码:
ClientSock1.sin_family = AF_INET;
ClientSock1.sin_port = htons(PORT1);
ClientSock1.sin_addr.s_addr = inet_addr("127.0.0.1");
1
2
3
1
2
3
连接代码
if(connect(sockfd1,(struct sockaddr*)&ClientSock1,ClientLen1)==-1){
printf(“connect error”);
exit(1);
}
1
2
3
4
1
2
3
4
返回值:
0 -成功 ,-1 - 失败,errno 为错误代码
4.int bind(int sockfd,struct sockaddr *myaddr,int addrlen);
功能:绑定本地地址和端口
参数:
sockfd-socket描述符
myaddr-自己的地址
addrlen-地址结构长度
返回值:
0-成功,-1-失败,errno为错误代码
注意:
服务器和客户端均可以绑定socket地址,但客户端通常不绑定自己的socket地址,而是系统随机分配一个端口,由该端口和本机ip地址填充套接字地址。
if(bind(sockfd,(struct sockaddr*)&serverAddr,serverLen)==-1){
printf(“bind error”);
exit(1);
}
1
2
3
4
1
2
3
4
5.int listen(int sockfd,int qlen)
功能:监听本地地址和端口
参数:
sockfd-已绑定的socket描述符
qlen - socket能处理的最大并发连接数
返回值
0-成功,-1-失败,errno为错误代码
listen(sockfd,BACKLOG);
1
1
6.int accept(int sockfd,struct sockaddr *clientaddr,int addrlen);
功能:接受连接
参数:
sockfd-socket描述符
clientaddr-客户端地址
addrlen-地址结构长度
返回值
0-成功,返回新的socket描述符标识已接受的连接 ,-1-失败,errno为错误代码
new_fd=accept(sockfd,(struct sockaddr*)&clientAddr,&clientLen);
if(new_fd == -1){
printf(“accept error”);
exit(1);
}
1
2
3
4
5
1
2
3
4
5
7.int read(int fd,char *buf,int len);
功能:从socket读取数据
参数:
fd-socket描述符
buf-接收数据缓冲区
len-要读取数据大小
返回值
≥0-成功,-1-失败,errno为错误代码
说明:
1.系统接收缓冲区中的数据大于参数len时返回len
2.缓冲区中的数据小于参数len时返回实际长度
3.接收缓冲区中没有数据时read函数阻塞,出现下列情况时返回收到数据:
连接被关闭,返回0
连接被复位,返回错误
阻塞过程中收到中断信号,errno=EINTR
读取完整数据的read_all函数
8.int write(int fd,char *buf,int len);
参数:
同上
9.int close(int sockfd)
功能:关闭socket
参数:
sockfd-socket描述符
返回值
0-成功,-1-失败,errno为错误代码
说明
调用close只是将对sockfd的引用减1,直到对sockfd的引用为0时才清除sockfd ,TCP协议将继续使用 sockfd,直到所有数据发送完成
实际案例说明
现在我们用上述函数实现一个简单的CS模型:包含一个客户端,两个服务器
客户端同时连接服务器1,服务器2。
客户端生成两个随机数,将其发给服务器1,服务器2
服务器1接受数据,并返回两个数的和
服务器2接受数据,并返回两个数的差
代码如下:
client.c
include
include
include
include
include
include
include
define PORT1 3002
define PORT2 4001
define MAXDATASIZE 128
int main(){
int sockfd1,ClientLen1,sockfd2,ClientLen2,a,b;
struct sockaddr_in ClientSock1,ClientSock2;
char buf[MAXDATASIZE];
srand(time(NULL));
a = random()%100;
b = random()%100;
sockfd1 = socket(AF_INET,SOCK_STREAM,0);//创建套接字
if(sockfd1==-1){
printf("create sockfd1 error");
exit(1);
}
//填充套接字地址
bzero(&ClientSock1,sizeof(ClientSock1));
ClientSock1.sin_family = AF_INET;
ClientSock1.sin_port = htons(PORT1);
ClientSock1.sin_addr.s_addr = inet_addr("127.0.0.1");
ClientLen1 = sizeof(ClientSock1);
//连接服务器
if(connect(sockfd1,(struct sockaddr*)&ClientSock1,ClientLen1)==-1){
printf("connect error");
exit(1);
}
bzero(buf,sizeof(buf));
sprintf(buf,"%d",a);
write(sockfd1,buf,MAXDATASIZE);
bzero(buf,sizeof(buf));
sprintf(buf,"%d",b);
write(sockfd1,buf,MAXDATASIZE);
bzero(buf,sizeof(buf));
read(sockfd1,buf,sizeof(buf));
printf("server1's reply:%s\n",buf);
sleep(1);
sockfd2 = socket(AF_INET,SOCK_STREAM,0);
if(sockfd2 == -1){
printf("create sockfd2 error");
exit(1);
}
bzero(&ClientSock2,sizeof(ClientSock2));
ClientSock2.sin_family = AF_INET;
ClientSock2.sin_port = htons(PORT2);
ClientSock2.sin_addr.s_addr = inet_addr("127.0.0.1");
ClientLen2 = sizeof(ClientSock2);
if(connect(sockfd2,(struct sockaddr*)&ClientSock2,ClientLen2)==-1){
printf("connect2 error");
exit(1);
}
bzero(buf,sizeof(buf));
sprintf(buf,"%d",a);
write(sockfd2,buf,MAXDATASIZE);
bzero(buf,sizeof(buf));
sprintf(buf,"%d",b);
write(sockfd2,buf,MAXDATASIZE);
bzero(buf,sizeof(buf));
read(sockfd2,buf,MAXDATASIZE);
printf("server2's reply:%s\n",buf);
close(sockfd1);
close(sockfd2);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
server1.c //接收并返回和
include
include
include
include
include
include
define PORT 3002
define MAXDATASIZE 128
define BACKLOG 5
int main(){
int sockfd,new_fd,a,b,result;
struct sockaddr_in serverAddr,clientAddr;
char buf[MAXDATASIZE];
socklen_t serverLen,clientLen;
sockfd = socket(AF_INET,SOCK_STREAM,0);
bzero(&serverAddr,sizeof(serverAddr));
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(PORT);
serverAddr.sin_addr.s_addr = htonl(INADDR_ANY);
serverLen = sizeof(serverAddr);
if(bind(sockfd,(struct sockaddr*)&serverAddr,serverLen)==-1){
printf("bind error");
exit(1);
}
listen(sockfd,BACKLOG);
for(;;){
clientLen = sizeof(clientAddr);
new_fd=accept(sockfd,(struct sockaddr*)&clientAddr,&clientLen);
if(new_fd == -1){
printf("accept error");
continue;
}
bzero(buf,sizeof(buf));
read(new_fd,buf,MAXDATASIZE);
a = atoi(buf);
sleep(1);
bzero(buf,sizeof(buf));
read(new_fd,buf,MAXDATASIZE);
b = atoi(buf);
result = a + b;
bzero(buf,sizeof(buf));
sprintf(buf,"%d",result);
write(new_fd,buf,MAXDATASIZE);
close(new_fd);
}
close(sockfd);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
server2.c //返回差
include
include
include
include
include
include
define PORT 4001
define MAXDATASIZE 128
define BACKLOG 5
int main(){
int sockfd,new_fd,a,b,result;
struct sockaddr_in serverAddr,clientAddr;
char buf[MAXDATASIZE];
socklen_t serverLen,clientLen;
sockfd = socket(AF_INET,SOCK_STREAM,0);
bzero(&serverAddr,sizeof(serverAddr));
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(PORT);
serverAddr.sin_addr.s_addr = htonl(INADDR_ANY);
serverLen = sizeof(serverAddr);
if(bind(sockfd,(struct sockaddr*)&serverAddr,serverLen)==-1){
printf("bind error");
exit(1);
}
listen(sockfd,BACKLOG);
clientLen = sizeof(clientAddr);
new_fd=accept(sockfd,(struct sockaddr*)&clientAddr,&clientLen);
if(new_fd == -1){
printf("accept error");
exit(1);
}
bzero(buf,sizeof(buf));
read(new_fd,buf,MAXDATASIZE);
a = atoi(buf);
sleep(1);
bzero(buf,sizeof(buf));
read(new_fd,buf,MAXDATASIZE);
b = atoi(buf);
result = a - b;
bzero(buf,sizeof(buf));
sprintf(buf,"%d",result);
write(new_fd,buf,MAXDATASIZE);
close(new_fd);
close(sockfd);
}