1--基于TCP实现字符串对话
主要需求:
服务器端和客户端各传递 1 次字符串,基于 TCP 协议,传递字符串前先以 4 字节整数型方式传递字符串长度,剩余部分为字符串数据;
注:下面的代码基于 Windows 系统实现;
1-1--服务器端
cpp
// gcc string_server_win.c -o string_server_win -lwsock32
// string_server_win 9190
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winsock2.h>
#define BUF_SIZE 1024
#define Len_SIZE 4
void ErrorHandling(char *message){
fputs(message, stderr);
fputc('\n', stderr);
exit(1);
}
int main(int argc, char *argv[]){
if (argc != 2) {
printf("Usage: %s <port>\n", argv[0]);
exit(1);
}
WSADATA wsaData; // init Socket lib
if(WSAStartup(MAKEWORD(2, 2), &wsaData) != 0){
ErrorHandling("WSAStartup() error!");
}
int Serv_sock = socket(PF_INET, SOCK_STREAM, 0); // create socket
if (Serv_sock == -1) {
ErrorHandling("socket() error");
}
struct sockaddr_in serv_addr; // allocate ip, port
memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(atoi(argv[1]));
if (bind(Serv_sock, (struct sockaddr*) &serv_addr, sizeof(serv_addr)) == -1){
ErrorHandling("bind() error");
}
if (listen(Serv_sock, 5) == -1) { // ready
ErrorHandling("listen() error");
}
struct sockaddr_in clnt_addr;
int clnt_addr_size = sizeof(clnt_addr);
for (int i = 0; i < 5; ++i) {
int Clnt_sock = accept(Serv_sock, (struct sockaddr*) &clnt_addr, &clnt_addr_size); // accept
if (Clnt_sock == -1){
ErrorHandling("accept() error");
}
else{
printf("Connected client %d \n", i+1);
}
while(1) {
int over = 0, recv_len = 0, msg_len, recv_cnt;
char msg[BUF_SIZE];
while (recv_len == 0 || recv_len < msg_len + Len_SIZE) {
recv_cnt = recv(Clnt_sock, (char*)&msg[recv_len], BUF_SIZE, 0);
if (recv_cnt == -1) {
ErrorHandling("read() error!");
}
if (recv_cnt == 0) {
over = 1;
break;
}
recv_len += recv_cnt;
if (recv_len >= Len_SIZE) {
memcpy(&msg_len, msg, Len_SIZE);
}
}
msg[recv_len] = '\0';
if (over == 1) {
break;
}
printf("Message from client: %s", msg + Len_SIZE); // output message from client
fputs("Input message: ", stdout);
fgets(msg + Len_SIZE, BUF_SIZE - Len_SIZE, stdin); // input message
int len = strlen(msg + Len_SIZE);
memcpy(msg, &len, Len_SIZE);
send(Clnt_sock, msg, Len_SIZE + len, 0); // send message to client
}
closesocket(Clnt_sock);
}
closesocket(Serv_sock);
return 0;
}
1-2--客户端
cpp
// gcc string_client_win.c -o string_client_win -lwsock32
// string_client_win 127.0.0.1 9190
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winsock2.h>
#define BUF_SIZE 1024
#define Len_SIZE 4
void ErrorHandling(char *message){
fputs(message, stderr);
fputc('\n', stderr);
exit(1);
}
int main(int argc, char* argv[]){
if (argc != 3) {
printf("Usage: %s <IP> <port>\n", argv[0]);
exit(1);
}
WSADATA wsaData; // init socket lib
if(WSAStartup(MAKEWORD(2, 2), &wsaData) != 0){
ErrorHandling("WSAStartup() error!");
}
int sock = socket(PF_INET, SOCK_STREAM, 0); // create socket
if (sock == -1)
ErrorHandling("socket() error");
struct sockaddr_in serv_addr; // allocate ip, port
memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = inet_addr(argv[1]);
serv_addr.sin_port = htons(atoi(argv[2]));
if (connect(sock, (struct sockaddr*) &serv_addr, sizeof(serv_addr)) == -1){ // connect
ErrorHandling("connect() error");
}
else {
puts("Connected");
}
for(int i = 0; i < 3; i++) {
char msg[BUF_SIZE];
memset(msg, 0, BUF_SIZE);
fputs("Input message: ", stdout);
fgets(msg + Len_SIZE, BUF_SIZE - Len_SIZE, stdin); // input message
int len = strlen(msg + Len_SIZE);
memcpy(msg, &len, Len_SIZE);
send(sock, msg, Len_SIZE + len, 0); // send message to server
int recv_len = 0, msg_len = 0, recv_cnt = 0;
while (recv_len == 0 || recv_len < msg_len + Len_SIZE) {
recv_cnt = recv(sock, (char*)&msg, BUF_SIZE, 0);
recv_len += recv_cnt;
if (recv_len >= Len_SIZE) {
memcpy(&msg_len, msg, Len_SIZE);
}
}
msg[recv_len] = '\0';
printf("Message from server: %s", msg + Len_SIZE);
}
closesocket(sock);
return 0;
}
1-3--编译运行
bash
# 服务器端
gcc string_server_win.c -o string_server_win -lwsock32
string_server_win 9190
# 客户端
gcc string_client_win.c -o string_client_win -lwsock32
string_client_win 127.0.0.1 9190