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端。
View Code#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端。
View CodeClient端。
View Code
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 }
