Socket编程
Socket编程很简单。因为不管用什么语言、什么环境编写,都是那几个固定的步骤。
Socket可以通过TCP\IP和UDP两种方式实现。
TCP\IP
tcp建立连接要进行“三次握手”,即交换三个分组。大致流程如下:
- 客户端向服务器发送一个SYN J
- 服务器向客户端响应一个SYN K,并对SYN J进行确认ACK J+1
- 客户端再想服务器发一个确认ACK K+1
当客户端调用connect时,触发了连接请求,向服务器发送了SYN J包,这时connect进入阻塞状态;服务器监听到连接请求,即收到SYN J包,调用accept函数接收请求向客户端发送SYN K ,ACK J+1,这时accept进入阻塞状态;客户端收到服务器的SYN K ,ACK J+1之后,这时connect返回,并对SYN K进行确认;服务器收到ACK K+1时,accept返回,至此三次握手完毕,连接建立。
Linux下实现,看下面的例子。windows下微软已经封装很好了,更简单一些,这里不赘述。
一、Server端。
#include <stdlib.h> #include <stdio.h> #include <sys/socket.h> #include <netinet/in.h> #include <fcntl.h> #include <string.h> int open_file(const char* filename) { int fd; if ((fd = open(filename, O_CREAT | O_RDWR, 0666)) < 0) { printf("open error"); return 0; } else { // printf("Open file%d\n", fd); } return fd; } void write_file(int fd, char *buf, int len) { lseek(fd, 0, SEEK_END); if (write(fd, buf, len) < 0) { printf("write error"); } else { // printf("Write: %s\n", buf); } } void read_file(int fd, int len) { char buff[len + 1]; lseek(fd, 0, SEEK_SET); if (read(fd, buff, len) < 0) { printf("read error"); } else { buff[len] = '\0'; // printf("read from file: %s\n", buff); } } void close_file(int fd) { if (close(fd) < 0) { printf("close error"); } else {//do nothing, close file right } } int main(int argc, char *argv[]) { // Get Port option if (argc < 2) { fprintf(stderr, "ERROR, no port provided\n"); exit(1); } int port_no = atoi(argv[1]); // Get socket int socket_fd = socket(AF_INET, SOCK_STREAM, 0); // Bind struct sockaddr_in server_addr; bzero((char *) &server_addr, sizeof(server_addr)); server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = INADDR_ANY; server_addr.sin_port = htons(port_no); bind(socket_fd, (struct sockaddr *) &server_addr, sizeof(server_addr)); // Listen listen(socket_fd, 5); while (1) { // Accept struct sockaddr_in client_addr; socklen_t client_addr_length = sizeof(client_addr); int socket_to_client = accept(socket_fd, (struct sockaddr *) &client_addr, &client_addr_length); // Read the buffer from the socket char buffer[1024*10240]; bzero(buffer, sizeof(buffer)); read(socket_to_client, buffer, sizeof(buffer) - 1);
//上面这个函数可以用下面的这个代替
//recv(socket_toclient, buffer, sizeof(buffer)-1, 0);
//printf("Here is the message: %s\n", buffer); //write the string into the file int fd = open_file("server.log"); if(fd > 0) { int len = strlen(buffer); write_file(fd, buffer, len); close_file(fd); } // Write const char *data = "I got your message."; write(socket_to_client, data, strlen(data)); // Close close(socket_to_client); } close(socket_fd); return 0; }
二、Client端。
View Code
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <string.h>
#include <netdb.h> // bcopy
#include <stdlib.h>
int main(int argc, char *argv[])
{
// Get options
if (argc < 3)
{
fprintf(stderr, "Usage: %s <hostname> <port>\n", argv[0]);
exit(1);
}
struct hostent *server_host = gethostbyname(argv[1]);
int server_port = atoi(argv[2]);
// Get socket
int socket_fd = socket(AF_INET, SOCK_STREAM, 0);
// Connect
struct sockaddr_in server_addr;
bzero((char *) &server_addr, sizeof(server_addr));
server_addr.sin_family = AF_INET;
bcopy((char *) server_host->h_addr, (char *) &server_addr.sin_addr.s_addr, server_host->h_length);
server_addr.sin_port = htons(server_port);
connect(socket_fd, (struct sockaddr *) &server_addr, sizeof(server_addr));
// Input
printf("Please enter the message: ");
char buffer[1024];
bzero(buffer, sizeof(buffer));
fgets(buffer, sizeof(buffer) - 1, stdin);
// Write
write(socket_fd, buffer, strlen(buffer));
// Read
bzero(buffer, sizeof(buffer));
read(socket_fd, buffer, sizeof(buffer) - 1);
printf("%s\n", buffer);
// Close
close(socket_fd);
return 0;
}
1 #include <sys/socket.h>
2 #include <netinet/in.h>
3 #include <stdio.h>
4 #include <string.h>
5 #include <netdb.h> // bcopy
6 #include <stdlib.h>
7
8 int main(int argc, char *argv[])
9 {
10 // Get options
11 if (argc < 3)
12 {
13 fprintf(stderr, "Usage: %s <hostname> <port>\n", argv[0]);
14 exit(1);
15 }
16 struct hostent *server_host = gethostbyname(argv[1]);
17 int server_port = atoi(argv[2]);
18
19 // Get socket
20 int socket_fd = socket(AF_INET, SOCK_STREAM, 0);
21
22 // Connect
23 struct sockaddr_in server_addr;
24 bzero((char *) &server_addr, sizeof(server_addr));
25 server_addr.sin_family = AF_INET;
26 bcopy((char *) server_host->h_addr, (char *) &server_addr.sin_addr.s_addr, server_host->h_length);
27 server_addr.sin_port = htons(server_port);
28 connect(socket_fd, (struct sockaddr *) &server_addr, sizeof(server_addr));
29
30 // Input
31 printf("Please enter the message: ");
32 char buffer[1024];
33 bzero(buffer, sizeof(buffer));
34 fgets(buffer, sizeof(buffer) - 1, stdin);
35
36 // Write
37 write(socket_fd, buffer, strlen(buffer));
38
39 // Read
40 bzero(buffer, sizeof(buffer));
41 read(socket_fd, buffer, sizeof(buffer) - 1);
42 printf("%s\n", buffer);
43
44 // Close
45 close(socket_fd);
46
47 return 0;
48 }
UDP
看例子代码。
Server端。
Client端。
1 #include <sys/socket.h>
2 #include <string.h>
3 #include <netinet/in.h>
4 #include <netdb.h>
5
6 int main(int argc, char *argv[])
7 {
8 // Create socket
9 int socket_fd = socket(AF_INET, SOCK_DGRAM, 0);
10
11 // Initialize server address
12 struct hostent *server_host = gethostbyname(argv[1]);
13 struct sockaddr_in server_addr;
14 server_addr.sin_family = AF_INET; // socket internet family
15 bcopy((char *)server_host->h_addr, (char *)&server_addr.sin_addr.s_addr, server_host->h_length); // socket internet address
16 server_addr.sin_port = htons(atoi(argv[2])); // socket internet port
17
18 // Send
19 char buffer[1024];
20 sendto(socket_fd, buffer, sizeof(buffer), 0, (const struct sockaddr *) &server_addr, sizeof(struct sockaddr_in));
21
22 // Receive and write
23 struct sockaddr_in client_addr;
24 socklen_t client_addr_length = sizeof(client_addr);
25 int msg_recv_length = recvfrom(socket_fd, buffer, sizeof(buffer), 0, (struct sockaddr *) &client_addr, &client_addr_length);
26 const char *hint = "Got an ACK: ";
27 write(1, hint, strlen(hint));
28 write(1, buffer, msg_recv_length);
29
30 // Close
31 close(socket_fd);
32
33 return 0;
34 }